12654012fSReza Sabdar /* 2*86c48bbfSReza Sabdar * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 32654012fSReza Sabdar * Use is subject to license terms. 42654012fSReza Sabdar */ 52654012fSReza Sabdar 62654012fSReza Sabdar /* 72654012fSReza Sabdar * BSD 3 Clause License 82654012fSReza Sabdar * 92654012fSReza Sabdar * Copyright (c) 2007, The Storage Networking Industry Association. 102654012fSReza Sabdar * 112654012fSReza Sabdar * Redistribution and use in source and binary forms, with or without 122654012fSReza Sabdar * modification, are permitted provided that the following conditions 132654012fSReza Sabdar * are met: 142654012fSReza Sabdar * - Redistributions of source code must retain the above copyright 152654012fSReza Sabdar * notice, this list of conditions and the following disclaimer. 162654012fSReza Sabdar * 172654012fSReza Sabdar * - Redistributions in binary form must reproduce the above copyright 182654012fSReza Sabdar * notice, this list of conditions and the following disclaimer in 192654012fSReza Sabdar * the documentation and/or other materials provided with the 202654012fSReza Sabdar * distribution. 212654012fSReza Sabdar * 222654012fSReza Sabdar * - Neither the name of The Storage Networking Industry Association (SNIA) 232654012fSReza Sabdar * nor the names of its contributors may be used to endorse or promote 242654012fSReza Sabdar * products derived from this software without specific prior written 252654012fSReza Sabdar * permission. 262654012fSReza Sabdar * 272654012fSReza Sabdar * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 282654012fSReza Sabdar * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 292654012fSReza Sabdar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 302654012fSReza Sabdar * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 312654012fSReza Sabdar * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 322654012fSReza Sabdar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 332654012fSReza Sabdar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 342654012fSReza Sabdar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 352654012fSReza Sabdar * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 362654012fSReza Sabdar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 372654012fSReza Sabdar * POSSIBILITY OF SUCH DAMAGE. 382654012fSReza Sabdar */ 392654012fSReza Sabdar /* Copyright (c) 2007, The Storage Networking Industry Association. */ 402654012fSReza Sabdar /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */ 412654012fSReza Sabdar 422654012fSReza Sabdar #include <sys/types.h> 432654012fSReza Sabdar #include <sys/socket.h> 442654012fSReza Sabdar #include <sys/time.h> 452654012fSReza Sabdar #include <sys/uio.h> 462654012fSReza Sabdar #include <unistd.h> 472654012fSReza Sabdar #include <string.h> 482654012fSReza Sabdar #include <stdlib.h> 492654012fSReza Sabdar #include <errno.h> 502654012fSReza Sabdar #include <netdb.h> 512654012fSReza Sabdar #include <netinet/in.h> 522654012fSReza Sabdar #include <arpa/inet.h> 532654012fSReza Sabdar #include "ndmpd.h" 542654012fSReza Sabdar #include "ndmpd_common.h" 552654012fSReza Sabdar 562654012fSReza Sabdar #define NDMP_PROC_ERR -1 572654012fSReza Sabdar #define NDMP_PROC_MSG 1 582654012fSReza Sabdar #define NDMP_PROC_REP 0 592654012fSReza Sabdar #define NDMP_PROC_REP_ERR 2 602654012fSReza Sabdar 612654012fSReza Sabdar /* 622654012fSReza Sabdar * The ndmp connection version can be set through command line. If command line 632654012fSReza Sabdar * is not specified it will be set from the ndmp SMF version property. 642654012fSReza Sabdar */ 652654012fSReza Sabdar int ndmp_ver = 0; 662654012fSReza Sabdar 672654012fSReza Sabdar /* 682654012fSReza Sabdar * The NDMP listening port number 692654012fSReza Sabdar */ 702654012fSReza Sabdar int ndmp_port = 0; 712654012fSReza Sabdar 722654012fSReza Sabdar /* 732654012fSReza Sabdar * Restore path mechanism definition 742654012fSReza Sabdar * 0 means partial path restore and 752654012fSReza Sabdar * 1 means full path restore. 762654012fSReza Sabdar * Refer to NDMP_FULL_RESTORE_PATH for partial path and full path definition. 772654012fSReza Sabdar */ 782654012fSReza Sabdar int ndmp_full_restore_path = 1; 792654012fSReza Sabdar 802654012fSReza Sabdar /* 812654012fSReza Sabdar * Do we support Direct Access Restore? 822654012fSReza Sabdar */ 832654012fSReza Sabdar int ndmp_dar_support = 0; 842654012fSReza Sabdar 852654012fSReza Sabdar /* 862654012fSReza Sabdar * ndmp_connection_t handler function 872654012fSReza Sabdar */ 882654012fSReza Sabdar static ndmpd_file_handler_func_t connection_file_handler; 892654012fSReza Sabdar 902654012fSReza Sabdar extern ndmp_handler_t ndmp_msghdl_tab[]; 912654012fSReza Sabdar 922654012fSReza Sabdar static int ndmp_readit(void *connection_handle, 932654012fSReza Sabdar caddr_t buf, 942654012fSReza Sabdar int len); 952654012fSReza Sabdar static int ndmp_writeit(void *connection_handle, 962654012fSReza Sabdar caddr_t buf, 972654012fSReza Sabdar int len); 982654012fSReza Sabdar static int ndmp_recv_msg(ndmp_connection_t *connection); 992654012fSReza Sabdar static int ndmp_process_messages(ndmp_connection_t *connection, 1002654012fSReza Sabdar boolean_t reply_expected); 1012654012fSReza Sabdar static ndmp_msg_handler_t *ndmp_get_handler(ndmp_connection_t *connection, 1022654012fSReza Sabdar ndmp_message message); 1032654012fSReza Sabdar static boolean_t ndmp_check_auth_required(ndmp_message message); 1042654012fSReza Sabdar static ndmp_handler_t *ndmp_get_interface(ndmp_message message); 1052654012fSReza Sabdar void *ndmpd_worker(void *ptarg); 1062654012fSReza Sabdar 1072654012fSReza Sabdar #ifdef lint 1082654012fSReza Sabdar bool_t 1092654012fSReza Sabdar xdr_ndmp_header(XDR *xdrs, ndmp_header *objp) 1102654012fSReza Sabdar { 1112654012fSReza Sabdar xdrs = xdrs; 1122654012fSReza Sabdar objp = objp; 1132654012fSReza Sabdar return (0); 1142654012fSReza Sabdar } 1152654012fSReza Sabdar #endif /* lint */ 1162654012fSReza Sabdar 1172654012fSReza Sabdar /* 1182654012fSReza Sabdar * ndmp_create_connection 1192654012fSReza Sabdar * 1202654012fSReza Sabdar * Allocate and initialize a connection structure. 1212654012fSReza Sabdar * 1222654012fSReza Sabdar * Parameters: 1232654012fSReza Sabdar * handler_tbl (input) - message handlers. 1242654012fSReza Sabdar * 1252654012fSReza Sabdar * Returns: 1262654012fSReza Sabdar * NULL - error 1272654012fSReza Sabdar * connection pointer 1282654012fSReza Sabdar * 1292654012fSReza Sabdar * Notes: 1302654012fSReza Sabdar * The returned connection should be destroyed using 1312654012fSReza Sabdar * ndmp_destroy_connection(). 1322654012fSReza Sabdar */ 1332654012fSReza Sabdar ndmp_connection_t * 1342654012fSReza Sabdar ndmp_create_connection(void) 1352654012fSReza Sabdar { 1362654012fSReza Sabdar ndmp_connection_t *connection; 1372654012fSReza Sabdar 1382654012fSReza Sabdar connection = ndmp_malloc(sizeof (ndmp_connection_t)); 1392654012fSReza Sabdar if (connection == NULL) 1402654012fSReza Sabdar return (NULL); 1412654012fSReza Sabdar 1422654012fSReza Sabdar connection->conn_sock = -1; 1432654012fSReza Sabdar connection->conn_my_sequence = 0; 1442654012fSReza Sabdar connection->conn_authorized = FALSE; 1452654012fSReza Sabdar connection->conn_eof = FALSE; 1462654012fSReza Sabdar connection->conn_msginfo.mi_body = 0; 1472654012fSReza Sabdar connection->conn_version = ndmp_ver; 1482654012fSReza Sabdar connection->conn_client_data = 0; 1492654012fSReza Sabdar (void) mutex_init(&connection->conn_lock, 0, NULL); 1502654012fSReza Sabdar connection->conn_xdrs.x_ops = 0; 1512654012fSReza Sabdar 1522654012fSReza Sabdar xdrrec_create(&connection->conn_xdrs, 0, 0, (caddr_t)connection, 1532654012fSReza Sabdar ndmp_readit, ndmp_writeit); 1542654012fSReza Sabdar 1552654012fSReza Sabdar if (connection->conn_xdrs.x_ops == 0) { 1562654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "xdrrec_create failed"); 1572654012fSReza Sabdar (void) mutex_destroy(&connection->conn_lock); 1582654012fSReza Sabdar (void) close(connection->conn_sock); 1592654012fSReza Sabdar free(connection); 1602654012fSReza Sabdar return (0); 1612654012fSReza Sabdar } 1622654012fSReza Sabdar return ((ndmp_connection_t *)connection); 1632654012fSReza Sabdar } 1642654012fSReza Sabdar 1652654012fSReza Sabdar /* 1662654012fSReza Sabdar * ndmp_destroy_connection 1672654012fSReza Sabdar * 1682654012fSReza Sabdar * Shutdown a connection and release allocated resources. 1692654012fSReza Sabdar * 1702654012fSReza Sabdar * Parameters: 1712654012fSReza Sabdar * connection_handle (Input) - connection handle. 1722654012fSReza Sabdar * 1732654012fSReza Sabdar * Returns: 1742654012fSReza Sabdar * void 1752654012fSReza Sabdar */ 1762654012fSReza Sabdar void 1772654012fSReza Sabdar ndmp_destroy_connection(ndmp_connection_t *connection_handle) 1782654012fSReza Sabdar { 1792654012fSReza Sabdar ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 1802654012fSReza Sabdar 1812654012fSReza Sabdar if (connection->conn_sock >= 0) { 1822654012fSReza Sabdar (void) mutex_destroy(&connection->conn_lock); 1832654012fSReza Sabdar (void) close(connection->conn_sock); 1842654012fSReza Sabdar connection->conn_sock = -1; 1852654012fSReza Sabdar } 1862654012fSReza Sabdar xdr_destroy(&connection->conn_xdrs); 1872654012fSReza Sabdar free(connection); 1882654012fSReza Sabdar } 1892654012fSReza Sabdar 1902654012fSReza Sabdar 1912654012fSReza Sabdar /* 1922654012fSReza Sabdar * ndmp_close 1932654012fSReza Sabdar * 1942654012fSReza Sabdar * Close a connection. 1952654012fSReza Sabdar * 1962654012fSReza Sabdar * Parameters: 1972654012fSReza Sabdar * connection_handle (Input) - connection handle. 1982654012fSReza Sabdar * 1992654012fSReza Sabdar * Returns: 2002654012fSReza Sabdar * void 2012654012fSReza Sabdar */ 2022654012fSReza Sabdar void 2032654012fSReza Sabdar ndmp_close(ndmp_connection_t *connection_handle) 2042654012fSReza Sabdar { 2052654012fSReza Sabdar ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 2062654012fSReza Sabdar 2072654012fSReza Sabdar ndmpd_audit_disconnect(connection); 2082654012fSReza Sabdar if (connection->conn_sock >= 0) { 2092654012fSReza Sabdar (void) mutex_destroy(&connection->conn_lock); 2102654012fSReza Sabdar (void) close(connection->conn_sock); 2112654012fSReza Sabdar connection->conn_sock = -1; 2122654012fSReza Sabdar } 2132654012fSReza Sabdar connection->conn_eof = TRUE; 2142654012fSReza Sabdar 2152654012fSReza Sabdar /* 2162654012fSReza Sabdar * We should close all the tapes that are used by this connection. 2172654012fSReza Sabdar * In some cases the ndmp client opens a tape, but does not close the 2182654012fSReza Sabdar * tape and closes the connection. 2192654012fSReza Sabdar */ 2202654012fSReza Sabdar ndmp_open_list_release(connection_handle); 2212654012fSReza Sabdar } 2222654012fSReza Sabdar 2232654012fSReza Sabdar /* 2242654012fSReza Sabdar * ndmp_start_worker 2252654012fSReza Sabdar * 2262654012fSReza Sabdar * Initializes and starts a ndmp_worker thread 2272654012fSReza Sabdar */ 2282654012fSReza Sabdar int 2292654012fSReza Sabdar ndmp_start_worker(ndmpd_worker_arg_t *argp) 2302654012fSReza Sabdar { 2312654012fSReza Sabdar pthread_attr_t tattr; 2322654012fSReza Sabdar int rc; 2332654012fSReza Sabdar 2342654012fSReza Sabdar (void) pthread_attr_init(&tattr); 2352654012fSReza Sabdar (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 2362654012fSReza Sabdar rc = pthread_create(NULL, &tattr, ndmpd_worker, (void *)argp); 2372654012fSReza Sabdar (void) pthread_attr_destroy(&tattr); 2382654012fSReza Sabdar return (rc); 2392654012fSReza Sabdar } 2402654012fSReza Sabdar 2412654012fSReza Sabdar /* 2422654012fSReza Sabdar * ndmp_run 2432654012fSReza Sabdar * 2442654012fSReza Sabdar * Creates a socket for listening and accepting connections 2452654012fSReza Sabdar * from NDMP clients. 2462654012fSReza Sabdar * Accepts connections and passes each connection to the connection 2472654012fSReza Sabdar * handler. 2482654012fSReza Sabdar * 2492654012fSReza Sabdar * Parameters: 2502654012fSReza Sabdar * port (input) - NDMP server port. 2512654012fSReza Sabdar * If 0, the port number will be retrieved from 2522654012fSReza Sabdar * the network service database. If not found there, 2532654012fSReza Sabdar * the default NDMP port number (from ndmp.x) 2542654012fSReza Sabdar * will be used. 2552654012fSReza Sabdar * handler (input) - connection handler function. 2562654012fSReza Sabdar * 2572654012fSReza Sabdar * Returns: 2582654012fSReza Sabdar * This function normally never returns unless there's error. 2592654012fSReza Sabdar * -1 : error 2602654012fSReza Sabdar * 2612654012fSReza Sabdar * Notes: 2622654012fSReza Sabdar * This function does not return unless encountering an error 2632654012fSReza Sabdar * related to the listen socket. 2642654012fSReza Sabdar */ 2652654012fSReza Sabdar int 2662654012fSReza Sabdar ndmp_run(ulong_t port, ndmp_con_handler_func_t con_handler_func) 2672654012fSReza Sabdar { 2682654012fSReza Sabdar int ns; 2692654012fSReza Sabdar int on, tmp; 2702654012fSReza Sabdar int server_socket; 2712654012fSReza Sabdar unsigned int ipaddr; 2722654012fSReza Sabdar struct sockaddr_in sin; 2732654012fSReza Sabdar int flag = 1; 2742654012fSReza Sabdar ndmpd_worker_arg_t *argp; 2752654012fSReza Sabdar 2762654012fSReza Sabdar sin.sin_family = AF_INET; 2772654012fSReza Sabdar sin.sin_addr.s_addr = INADDR_ANY; 2782654012fSReza Sabdar sin.sin_port = htons(port); 2792654012fSReza Sabdar 2802654012fSReza Sabdar if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 2812654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Socket error: %m"); 2822654012fSReza Sabdar return (-1); 2832654012fSReza Sabdar } 2842654012fSReza Sabdar 2852654012fSReza Sabdar on = 1; 2862654012fSReza Sabdar (void) setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, 2872654012fSReza Sabdar (char *)&on, sizeof (on)); 2882654012fSReza Sabdar 2892654012fSReza Sabdar 2902654012fSReza Sabdar if (bind(server_socket, (struct sockaddr *)&sin, sizeof (sin)) < 0) { 2912654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "bind error: %m"); 2922654012fSReza Sabdar (void) close(server_socket); 2932654012fSReza Sabdar return (-1); 2942654012fSReza Sabdar } 2952654012fSReza Sabdar if (listen(server_socket, 5) < 0) { 2962654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "listen error: %m"); 2972654012fSReza Sabdar (void) close(server_socket); 2982654012fSReza Sabdar return (-1); 2992654012fSReza Sabdar } 3002654012fSReza Sabdar 3012654012fSReza Sabdar for (; ; ) { 3022654012fSReza Sabdar if ((ns = tcp_accept(server_socket, &ipaddr)) < 0) { 3032654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "tcp_accept error: %m"); 3042654012fSReza Sabdar continue; 3052654012fSReza Sabdar } 3062654012fSReza Sabdar 3072654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "connection fd: %d", ns); 3082654012fSReza Sabdar 3092654012fSReza Sabdar /* 3102654012fSReza Sabdar * 'css' and 'crs' in the following env variables stand for: 3112654012fSReza Sabdar * 'connection send size' and 'connection receive size'. 3122654012fSReza Sabdar */ 3132654012fSReza Sabdar tmp = atoi((const char *)ndmpd_get_prop_default(NDMP_SOCKET_CSS, 3142654012fSReza Sabdar "65")); 3152654012fSReza Sabdar if (tmp <= 0) 3162654012fSReza Sabdar tmp = 65; 3172654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "css: %d_KB", tmp); 3182654012fSReza Sabdar ndmp_set_socket_snd_buf(ns, tmp * KILOBYTE); 3192654012fSReza Sabdar 3202654012fSReza Sabdar tmp = atoi((const char *)ndmpd_get_prop_default(NDMP_SOCKET_CRS, 3212654012fSReza Sabdar "80")); 3222654012fSReza Sabdar if (tmp <= 0) 3232654012fSReza Sabdar tmp = 80; 3242654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "crs: %d_KB", tmp); 3252654012fSReza Sabdar ndmp_set_socket_rcv_buf(ns, tmp * KILOBYTE); 3262654012fSReza Sabdar 3272654012fSReza Sabdar ndmp_set_socket_nodelay(ns); 3282654012fSReza Sabdar (void) setsockopt(ns, SOL_SOCKET, SO_KEEPALIVE, &flag, 3292654012fSReza Sabdar sizeof (flag)); 3302654012fSReza Sabdar 3312654012fSReza Sabdar if ((argp = ndmp_malloc(sizeof (ndmpd_worker_arg_t))) != NULL) { 3322654012fSReza Sabdar argp->nw_sock = ns; 3332654012fSReza Sabdar argp->nw_ipaddr = ipaddr; 3342654012fSReza Sabdar argp->nw_con_handler_func = con_handler_func; 3352654012fSReza Sabdar (void) ndmp_start_worker(argp); 3362654012fSReza Sabdar } 3372654012fSReza Sabdar } 3382654012fSReza Sabdar } 3392654012fSReza Sabdar 3402654012fSReza Sabdar /* 3412654012fSReza Sabdar * ndmpd_worker thread 3422654012fSReza Sabdar * 3432654012fSReza Sabdar * Parameters: 3442654012fSReza Sabdar * argp (input) - structure containing socket and handler function 3452654012fSReza Sabdar * 3462654012fSReza Sabdar * Returns: 3472654012fSReza Sabdar * 0 - successful connection. 3482654012fSReza Sabdar * -1 - error. 3492654012fSReza Sabdar */ 3502654012fSReza Sabdar void * 3512654012fSReza Sabdar ndmpd_worker(void *ptarg) 3522654012fSReza Sabdar { 3532654012fSReza Sabdar int sock; 3542654012fSReza Sabdar ndmp_connection_t *connection; 3552654012fSReza Sabdar ndmpd_worker_arg_t *argp = (ndmpd_worker_arg_t *)ptarg; 3562654012fSReza Sabdar 3572654012fSReza Sabdar if (!argp) 3582654012fSReza Sabdar return ((void *)-1); 3592654012fSReza Sabdar 3602654012fSReza Sabdar NS_INC(trun); 3612654012fSReza Sabdar sock = argp->nw_sock; 3622654012fSReza Sabdar 3632654012fSReza Sabdar if ((connection = ndmp_create_connection()) == NULL) { 3642654012fSReza Sabdar (void) close(sock); 3652654012fSReza Sabdar free(argp); 3662654012fSReza Sabdar exit(1); 3672654012fSReza Sabdar } 3682654012fSReza Sabdar 3692654012fSReza Sabdar /* initialize auditing session */ 3702654012fSReza Sabdar if (adt_start_session(&connection->conn_ah, NULL, 0) != 0) { 3712654012fSReza Sabdar free(argp); 3722654012fSReza Sabdar return ((void *)-1); 3732654012fSReza Sabdar } 3742654012fSReza Sabdar 3752654012fSReza Sabdar ((ndmp_connection_t *)connection)->conn_sock = sock; 3762654012fSReza Sabdar (*argp->nw_con_handler_func)(connection); 3772654012fSReza Sabdar (void) adt_end_session(connection->conn_ah); 3782654012fSReza Sabdar ndmp_destroy_connection(connection); 3792654012fSReza Sabdar NS_DEC(trun); 3802654012fSReza Sabdar 3812654012fSReza Sabdar free(argp); 3822654012fSReza Sabdar return (NULL); 3832654012fSReza Sabdar } 3842654012fSReza Sabdar 3852654012fSReza Sabdar /* 3862654012fSReza Sabdar * ndmp_process_requests 3872654012fSReza Sabdar * 3882654012fSReza Sabdar * Reads the next request message into the stream buffer. 3892654012fSReza Sabdar * Processes messages until the stream buffer is empty. 3902654012fSReza Sabdar * 3912654012fSReza Sabdar * Parameters: 3922654012fSReza Sabdar * connection_handle (input) - connection handle. 3932654012fSReza Sabdar * 3942654012fSReza Sabdar * Returns: 3952654012fSReza Sabdar * 0 - 1 or more messages successfully processed. 3962654012fSReza Sabdar * -1 - error; connection no longer established. 3972654012fSReza Sabdar */ 3982654012fSReza Sabdar int 3992654012fSReza Sabdar ndmp_process_requests(ndmp_connection_t *connection_handle) 4002654012fSReza Sabdar { 4012654012fSReza Sabdar int rv; 4022654012fSReza Sabdar ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 4032654012fSReza Sabdar 4042654012fSReza Sabdar (void) mutex_lock(&connection->conn_lock); 4052654012fSReza Sabdar rv = 0; 4062654012fSReza Sabdar if (ndmp_process_messages(connection, FALSE) < 0) 4072654012fSReza Sabdar rv = -1; 4082654012fSReza Sabdar 4092654012fSReza Sabdar (void) mutex_unlock(&connection->conn_lock); 4102654012fSReza Sabdar return (rv); 4112654012fSReza Sabdar } 4122654012fSReza Sabdar 4132654012fSReza Sabdar 4142654012fSReza Sabdar /* 4152654012fSReza Sabdar * ndmp_send_request 4162654012fSReza Sabdar * 4172654012fSReza Sabdar * Send an NDMP request message. 4182654012fSReza Sabdar * 4192654012fSReza Sabdar * Parameters: 4202654012fSReza Sabdar * connection_handle (input) - connection pointer. 4212654012fSReza Sabdar * message (input) - message number. 4222654012fSReza Sabdar * err (input) - error code to place in header. 4232654012fSReza Sabdar * request_data (input) - message body. 4242654012fSReza Sabdar * reply (output) - reply message. If 0, reply will be 4252654012fSReza Sabdar * discarded. 4262654012fSReza Sabdar * 4272654012fSReza Sabdar * Returns: 4282654012fSReza Sabdar * 0 - successful send. 4292654012fSReza Sabdar * -1 - error. 4302654012fSReza Sabdar * otherwise - error from reply header. 4312654012fSReza Sabdar * 4322654012fSReza Sabdar * Notes: 4332654012fSReza Sabdar * - The reply body is only returned if the error code is NDMP_NO_ERR. 4342654012fSReza Sabdar */ 4352654012fSReza Sabdar int 4362654012fSReza Sabdar ndmp_send_request(ndmp_connection_t *connection_handle, ndmp_message message, 4372654012fSReza Sabdar ndmp_error err, void *request_data, void **reply) 4382654012fSReza Sabdar { 4392654012fSReza Sabdar ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 4402654012fSReza Sabdar ndmp_header header; 4412654012fSReza Sabdar ndmp_msg_handler_t *handler; 4422654012fSReza Sabdar int r; 4432654012fSReza Sabdar struct timeval time; 4442654012fSReza Sabdar 4452654012fSReza Sabdar /* Lookup info necessary for processing this request. */ 4462654012fSReza Sabdar if (!(handler = ndmp_get_handler(connection, message))) { 4472654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Sending message 0x%x: not supported", 4482654012fSReza Sabdar message); 4492654012fSReza Sabdar return (-1); 4502654012fSReza Sabdar } 4512654012fSReza Sabdar (void) gettimeofday(&time, 0); 4522654012fSReza Sabdar 4532654012fSReza Sabdar header.sequence = ++(connection->conn_my_sequence); 4542654012fSReza Sabdar header.time_stamp = time.tv_sec; 4552654012fSReza Sabdar header.message_type = NDMP_MESSAGE_REQUEST; 4562654012fSReza Sabdar header.message = message; 4572654012fSReza Sabdar header.reply_sequence = 0; 4582654012fSReza Sabdar header.error = err; 4592654012fSReza Sabdar 4602654012fSReza Sabdar connection->conn_xdrs.x_op = XDR_ENCODE; 4612654012fSReza Sabdar if (!xdr_ndmp_header(&connection->conn_xdrs, &header)) { 4622654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 4632654012fSReza Sabdar "Sending message 0x%x: encoding request header", message); 4642654012fSReza Sabdar (void) xdrrec_endofrecord(&connection->conn_xdrs, 1); 4652654012fSReza Sabdar return (-1); 4662654012fSReza Sabdar } 4672654012fSReza Sabdar if (err == NDMP_NO_ERR && handler->mh_xdr_request && request_data) { 4682654012fSReza Sabdar if (!(*handler->mh_xdr_request)(&connection->conn_xdrs, 4692654012fSReza Sabdar request_data)) { 4702654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 4712654012fSReza Sabdar "Sending message 0x%x: encoding request body", 4722654012fSReza Sabdar message); 4732654012fSReza Sabdar (void) xdrrec_endofrecord(&connection->conn_xdrs, 1); 4742654012fSReza Sabdar return (-1); 4752654012fSReza Sabdar } 4762654012fSReza Sabdar } 4772654012fSReza Sabdar (void) xdrrec_endofrecord(&connection->conn_xdrs, 1); 4782654012fSReza Sabdar 4792654012fSReza Sabdar if (handler->mh_xdr_reply == 0) { 4802654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "handler->mh_xdr_reply == 0"); 4812654012fSReza Sabdar return (0); 4822654012fSReza Sabdar } 4832654012fSReza Sabdar 4842654012fSReza Sabdar /* 4852654012fSReza Sabdar * Process messages until the reply to this request has been 4862654012fSReza Sabdar * processed. 4872654012fSReza Sabdar */ 4882654012fSReza Sabdar for (; ; ) { 4892654012fSReza Sabdar r = ndmp_process_messages(connection, TRUE); 4902654012fSReza Sabdar 4912654012fSReza Sabdar /* connection error? */ 4922654012fSReza Sabdar if (r < 0) 4932654012fSReza Sabdar return (-1); 4942654012fSReza Sabdar 4952654012fSReza Sabdar /* no reply received? */ 4962654012fSReza Sabdar if (r == 0) 4972654012fSReza Sabdar continue; 4982654012fSReza Sabdar 4992654012fSReza Sabdar /* reply received? */ 5002654012fSReza Sabdar if (r == 1) { 5012654012fSReza Sabdar if (message != 5022654012fSReza Sabdar connection->conn_msginfo.mi_hdr.message) { 5032654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 5042654012fSReza Sabdar "Received unexpected reply 0x%x", 5052654012fSReza Sabdar connection->conn_msginfo.mi_hdr.message); 5062654012fSReza Sabdar ndmp_free_message(connection_handle); 5072654012fSReza Sabdar return (-1); 5082654012fSReza Sabdar } 5092654012fSReza Sabdar if (reply != NULL) 5102654012fSReza Sabdar *reply = connection->conn_msginfo.mi_body; 5112654012fSReza Sabdar else 5122654012fSReza Sabdar ndmp_free_message(connection_handle); 5132654012fSReza Sabdar 5142654012fSReza Sabdar return (connection->conn_msginfo.mi_hdr.error); 5152654012fSReza Sabdar } 5162654012fSReza Sabdar /* error handling reply */ 5172654012fSReza Sabdar 5182654012fSReza Sabdar return (-1); 5192654012fSReza Sabdar } 5202654012fSReza Sabdar } 5212654012fSReza Sabdar 5222654012fSReza Sabdar 5232654012fSReza Sabdar /* 5242654012fSReza Sabdar * ndmp_send_request_lock 5252654012fSReza Sabdar * 5262654012fSReza Sabdar * A wrapper for ndmp_send_request with locks. 5272654012fSReza Sabdar * 5282654012fSReza Sabdar * Parameters: 5292654012fSReza Sabdar * connection_handle (input) - connection pointer. 5302654012fSReza Sabdar * message (input) - message number. 5312654012fSReza Sabdar * err (input) - error code to place in header. 5322654012fSReza Sabdar * request_data (input) - message body. 5332654012fSReza Sabdar * reply (output) - reply message. If 0, reply will be 5342654012fSReza Sabdar * discarded. 5352654012fSReza Sabdar * 5362654012fSReza Sabdar * Returns: 5372654012fSReza Sabdar * 0 - successful send. 5382654012fSReza Sabdar * -1 - error. 5392654012fSReza Sabdar * otherwise - error from reply header. 5402654012fSReza Sabdar * 5412654012fSReza Sabdar * Notes: 5422654012fSReza Sabdar * - The reply body is only returned if the error code is NDMP_NO_ERR. 5432654012fSReza Sabdar */ 5442654012fSReza Sabdar int 5452654012fSReza Sabdar ndmp_send_request_lock(ndmp_connection_t *connection_handle, 5462654012fSReza Sabdar ndmp_message message, ndmp_error err, void *request_data, void **reply) 5472654012fSReza Sabdar { 5482654012fSReza Sabdar int rv; 5492654012fSReza Sabdar ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 5502654012fSReza Sabdar 5512654012fSReza Sabdar (void) mutex_lock(&connection->conn_lock); 5522654012fSReza Sabdar 5532654012fSReza Sabdar rv = ndmp_send_request(connection_handle, message, err, request_data, 5542654012fSReza Sabdar reply); 5552654012fSReza Sabdar (void) mutex_unlock(&connection->conn_lock); 5562654012fSReza Sabdar return (rv); 5572654012fSReza Sabdar } 5582654012fSReza Sabdar 5592654012fSReza Sabdar 5602654012fSReza Sabdar /* 5612654012fSReza Sabdar * ndmp_send_response 5622654012fSReza Sabdar * 5632654012fSReza Sabdar * Send an NDMP reply message. 5642654012fSReza Sabdar * 5652654012fSReza Sabdar * Parameters: 5662654012fSReza Sabdar * connection_handle (input) - connection pointer. 5672654012fSReza Sabdar * err (input) - error code to place in header. 5682654012fSReza Sabdar * reply (input) - reply message body. 5692654012fSReza Sabdar * 5702654012fSReza Sabdar * Returns: 5712654012fSReza Sabdar * 0 - successful send. 5722654012fSReza Sabdar * -1 - error. 5732654012fSReza Sabdar * 5742654012fSReza Sabdar * Notes: 5752654012fSReza Sabdar * - The body is only sent if the error code is NDMP_NO_ERR. 5762654012fSReza Sabdar */ 5772654012fSReza Sabdar int 5782654012fSReza Sabdar ndmp_send_response(ndmp_connection_t *connection_handle, ndmp_error err, 5792654012fSReza Sabdar void *reply) 5802654012fSReza Sabdar { 5812654012fSReza Sabdar ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 5822654012fSReza Sabdar ndmp_header header; 5832654012fSReza Sabdar struct timeval time; 5842654012fSReza Sabdar 5852654012fSReza Sabdar (void) gettimeofday(&time, 0); 5862654012fSReza Sabdar 5872654012fSReza Sabdar header.sequence = ++(connection->conn_my_sequence); 5882654012fSReza Sabdar header.time_stamp = time.tv_sec; 5892654012fSReza Sabdar header.message_type = NDMP_MESSAGE_REPLY; 5902654012fSReza Sabdar header.message = connection->conn_msginfo.mi_hdr.message; 5912654012fSReza Sabdar header.reply_sequence = connection->conn_msginfo.mi_hdr.sequence; 5922654012fSReza Sabdar header.error = err; 5932654012fSReza Sabdar 5942654012fSReza Sabdar connection->conn_xdrs.x_op = XDR_ENCODE; 5952654012fSReza Sabdar if (!xdr_ndmp_header(&connection->conn_xdrs, &header)) { 5962654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Sending message 0x%x: " 5972654012fSReza Sabdar "encoding reply header", 5982654012fSReza Sabdar header.message); 5992654012fSReza Sabdar (void) xdrrec_endofrecord(&connection->conn_xdrs, 1); 6002654012fSReza Sabdar return (-1); 6012654012fSReza Sabdar } 6022654012fSReza Sabdar if (err == NDMP_NO_ERR && 6032654012fSReza Sabdar connection->conn_msginfo.mi_handler->mh_xdr_reply && 6042654012fSReza Sabdar reply) { 6052654012fSReza Sabdar if (!(*connection->conn_msginfo.mi_handler->mh_xdr_reply)( 6062654012fSReza Sabdar &connection->conn_xdrs, reply)) { 6072654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 6082654012fSReza Sabdar "Sending message 0x%x: encoding reply body", 6092654012fSReza Sabdar header.message); 6102654012fSReza Sabdar (void) xdrrec_endofrecord(&connection->conn_xdrs, 1); 6112654012fSReza Sabdar return (-1); 6122654012fSReza Sabdar } 6132654012fSReza Sabdar } 6142654012fSReza Sabdar (void) xdrrec_endofrecord(&connection->conn_xdrs, 1); 6152654012fSReza Sabdar return (0); 6162654012fSReza Sabdar } 6172654012fSReza Sabdar 6182654012fSReza Sabdar /* 6192654012fSReza Sabdar * ndmp_free_message 6202654012fSReza Sabdar * 6212654012fSReza Sabdar * Free the memory of NDMP message body. 6222654012fSReza Sabdar * 6232654012fSReza Sabdar * Parameters: 6242654012fSReza Sabdar * connection_handle (input) - connection pointer. 6252654012fSReza Sabdar * 6262654012fSReza Sabdar * Returns: 6272654012fSReza Sabdar * void 6282654012fSReza Sabdar * 6292654012fSReza Sabdar */ 6302654012fSReza Sabdar void 6312654012fSReza Sabdar ndmp_free_message(ndmp_connection_t *connection_handle) 6322654012fSReza Sabdar { 6332654012fSReza Sabdar ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 6342654012fSReza Sabdar 6352654012fSReza Sabdar if (connection->conn_msginfo.mi_handler == NULL || 6362654012fSReza Sabdar connection->conn_msginfo.mi_body == NULL) 6372654012fSReza Sabdar return; 6382654012fSReza Sabdar 6392654012fSReza Sabdar connection->conn_xdrs.x_op = XDR_FREE; 6402654012fSReza Sabdar if (connection->conn_msginfo.mi_hdr.message_type == 6412654012fSReza Sabdar NDMP_MESSAGE_REQUEST) { 6422654012fSReza Sabdar if (connection->conn_msginfo.mi_handler->mh_xdr_request) 6432654012fSReza Sabdar (*connection->conn_msginfo.mi_handler->mh_xdr_request)( 6442654012fSReza Sabdar &connection->conn_xdrs, 6452654012fSReza Sabdar connection->conn_msginfo.mi_body); 6462654012fSReza Sabdar } else { 6472654012fSReza Sabdar if (connection->conn_msginfo.mi_handler->mh_xdr_reply) 6482654012fSReza Sabdar (*connection->conn_msginfo.mi_handler->mh_xdr_reply)( 6492654012fSReza Sabdar &connection->conn_xdrs, 6502654012fSReza Sabdar connection->conn_msginfo.mi_body); 6512654012fSReza Sabdar } 6522654012fSReza Sabdar 6532654012fSReza Sabdar (void) free(connection->conn_msginfo.mi_body); 6542654012fSReza Sabdar connection->conn_msginfo.mi_body = 0; 6552654012fSReza Sabdar } 6562654012fSReza Sabdar 6572654012fSReza Sabdar /* 6582654012fSReza Sabdar * ndmp_get_fd 6592654012fSReza Sabdar * 6602654012fSReza Sabdar * Returns the connection file descriptor. 6612654012fSReza Sabdar * 6622654012fSReza Sabdar * Parameters: 6632654012fSReza Sabdar * connection_handle (input) - connection handle 6642654012fSReza Sabdar * 6652654012fSReza Sabdar * Returns: 6662654012fSReza Sabdar * >=0 - file descriptor. 6672654012fSReza Sabdar * -1 - connection not open. 6682654012fSReza Sabdar */ 6692654012fSReza Sabdar int 6702654012fSReza Sabdar ndmp_get_fd(ndmp_connection_t *connection_handle) 6712654012fSReza Sabdar { 6722654012fSReza Sabdar return (((ndmp_connection_t *)connection_handle)->conn_sock); 6732654012fSReza Sabdar } 6742654012fSReza Sabdar 6752654012fSReza Sabdar 6762654012fSReza Sabdar /* 6772654012fSReza Sabdar * ndmp_set_client_data 6782654012fSReza Sabdar * 6792654012fSReza Sabdar * This function provides a means for the library client to provide 6802654012fSReza Sabdar * a pointer to some user data structure that is retrievable by 6812654012fSReza Sabdar * each message handler via ndmp_get_client_data. 6822654012fSReza Sabdar * 6832654012fSReza Sabdar * Parameters: 6842654012fSReza Sabdar * connection_handle (input) - connection handle. 6852654012fSReza Sabdar * client_data (input) - user data pointer. 6862654012fSReza Sabdar * 6872654012fSReza Sabdar * Returns: 6882654012fSReza Sabdar * void 6892654012fSReza Sabdar */ 6902654012fSReza Sabdar void 6912654012fSReza Sabdar ndmp_set_client_data(ndmp_connection_t *connection_handle, void *client_data) 6922654012fSReza Sabdar { 6932654012fSReza Sabdar ((ndmp_connection_t *)connection_handle)->conn_client_data = 6942654012fSReza Sabdar client_data; 6952654012fSReza Sabdar } 6962654012fSReza Sabdar 6972654012fSReza Sabdar 6982654012fSReza Sabdar /* 6992654012fSReza Sabdar * ndmp_get_client_data 7002654012fSReza Sabdar * 7012654012fSReza Sabdar * This function provides a means for the library client to provide 7022654012fSReza Sabdar * a pointer to some user data structure that is retrievable by 7032654012fSReza Sabdar * each message handler via ndmp_get_client_data. 7042654012fSReza Sabdar * 7052654012fSReza Sabdar * Parameters: 7062654012fSReza Sabdar * connection_handle (input) - connection handle. 7072654012fSReza Sabdar * 7082654012fSReza Sabdar * Returns: 7092654012fSReza Sabdar * client data pointer. 7102654012fSReza Sabdar */ 7112654012fSReza Sabdar void * 7122654012fSReza Sabdar ndmp_get_client_data(ndmp_connection_t *connection_handle) 7132654012fSReza Sabdar { 7142654012fSReza Sabdar return (((ndmp_connection_t *)connection_handle)->conn_client_data); 7152654012fSReza Sabdar } 7162654012fSReza Sabdar 7172654012fSReza Sabdar 7182654012fSReza Sabdar /* 7192654012fSReza Sabdar * ndmp_set_version 7202654012fSReza Sabdar * 7212654012fSReza Sabdar * Sets the NDMP protocol version to be used on the connection. 7222654012fSReza Sabdar * 7232654012fSReza Sabdar * Parameters: 7242654012fSReza Sabdar * connection_handle (input) - connection handle. 7252654012fSReza Sabdar * version (input) - protocol version. 7262654012fSReza Sabdar * 7272654012fSReza Sabdar * Returns: 7282654012fSReza Sabdar * void 7292654012fSReza Sabdar */ 7302654012fSReza Sabdar void 7312654012fSReza Sabdar ndmp_set_version(ndmp_connection_t *connection_handle, ushort_t version) 7322654012fSReza Sabdar { 7332654012fSReza Sabdar ((ndmp_connection_t *)connection_handle)->conn_version = version; 7342654012fSReza Sabdar } 7352654012fSReza Sabdar 7362654012fSReza Sabdar 7372654012fSReza Sabdar /* 7382654012fSReza Sabdar * ndmp_get_version 7392654012fSReza Sabdar * 7402654012fSReza Sabdar * Gets the NDMP protocol version in use on the connection. 7412654012fSReza Sabdar * 7422654012fSReza Sabdar * Parameters: 7432654012fSReza Sabdar * connection_handle (input) - connection handle. 7442654012fSReza Sabdar * version (input) - protocol version. 7452654012fSReza Sabdar * 7462654012fSReza Sabdar * Returns: 7472654012fSReza Sabdar * void 7482654012fSReza Sabdar */ 7492654012fSReza Sabdar ushort_t 7502654012fSReza Sabdar ndmp_get_version(ndmp_connection_t *connection_handle) 7512654012fSReza Sabdar { 7522654012fSReza Sabdar return (((ndmp_connection_t *)connection_handle)->conn_version); 7532654012fSReza Sabdar } 7542654012fSReza Sabdar 7552654012fSReza Sabdar 7562654012fSReza Sabdar /* 7572654012fSReza Sabdar * ndmp_set_authorized 7582654012fSReza Sabdar * 7592654012fSReza Sabdar * Mark the connection as either having been authorized or not. 7602654012fSReza Sabdar * 7612654012fSReza Sabdar * Parameters: 7622654012fSReza Sabdar * connection_handle (input) - connection handle. 7632654012fSReza Sabdar * authorized (input) - TRUE or FALSE. 7642654012fSReza Sabdar * 7652654012fSReza Sabdar * Returns: 7662654012fSReza Sabdar * void 7672654012fSReza Sabdar */ 7682654012fSReza Sabdar void 7692654012fSReza Sabdar ndmp_set_authorized(ndmp_connection_t *connection_handle, boolean_t authorized) 7702654012fSReza Sabdar { 7712654012fSReza Sabdar ((ndmp_connection_t *)connection_handle)->conn_authorized = authorized; 7722654012fSReza Sabdar } 7732654012fSReza Sabdar 7742654012fSReza Sabdar 7752654012fSReza Sabdar /* 7762654012fSReza Sabdar * ndmpd_main 7772654012fSReza Sabdar * 7782654012fSReza Sabdar * NDMP main function called from main(). 7792654012fSReza Sabdar * 7802654012fSReza Sabdar * Parameters: 7812654012fSReza Sabdar * void 7822654012fSReza Sabdar * 7832654012fSReza Sabdar * Returns: 7842654012fSReza Sabdar * void 7852654012fSReza Sabdar */ 7862654012fSReza Sabdar void 7872654012fSReza Sabdar ndmpd_main(void) 7882654012fSReza Sabdar { 7892654012fSReza Sabdar char *propval; 7902654012fSReza Sabdar 7912654012fSReza Sabdar ndmp_load_params(); 792*86c48bbfSReza Sabdar if (ndmp_log_open_file() != 0) { 793*86c48bbfSReza Sabdar NDMP_LOG(LOG_ERR, 794*86c48bbfSReza Sabdar "Could not open log file properly."); 795*86c48bbfSReza Sabdar } 796*86c48bbfSReza Sabdar 7972654012fSReza Sabdar /* 7982654012fSReza Sabdar * Find ndmp port number to be used. If ndmpd is run as command line 7992654012fSReza Sabdar * and port number is supplied, use that port number. If port number is 8002654012fSReza Sabdar * is not supplied, find out if ndmp port property is set. If ndmp 8012654012fSReza Sabdar * port property is set, use that port number otherwise use the defaule 8022654012fSReza Sabdar * port number. 8032654012fSReza Sabdar */ 8042654012fSReza Sabdar if (ndmp_port == 0) { 8052654012fSReza Sabdar if ((propval = ndmpd_get_prop(NDMP_TCP_PORT)) == NULL || 8062654012fSReza Sabdar *propval == 0) 8072654012fSReza Sabdar ndmp_port = NDMPPORT; 8082654012fSReza Sabdar else 8092654012fSReza Sabdar ndmp_port = strtol(propval, 0, 0); 8102654012fSReza Sabdar } 8112654012fSReza Sabdar 8122654012fSReza Sabdar if (ndmp_run(ndmp_port, connection_handler) == -1) 8132654012fSReza Sabdar perror("ndmp_run ERROR"); 8142654012fSReza Sabdar 8152654012fSReza Sabdar ndmp_log_close_file(); 8162654012fSReza Sabdar } 8172654012fSReza Sabdar 8182654012fSReza Sabdar /* 8192654012fSReza Sabdar * connection_handler 8202654012fSReza Sabdar * 8212654012fSReza Sabdar * NDMP connection handler. 8222654012fSReza Sabdar * Waits for, reads, and processes NDMP requests on a connection. 8232654012fSReza Sabdar * 8242654012fSReza Sabdar * Parameters: 8252654012fSReza Sabdar * connection (input) - connection handle. 8262654012fSReza Sabdar * 8272654012fSReza Sabdar * Return: 8282654012fSReza Sabdar * void 8292654012fSReza Sabdar */ 8302654012fSReza Sabdar void 8312654012fSReza Sabdar connection_handler(ndmp_connection_t *connection) 8322654012fSReza Sabdar { 8332654012fSReza Sabdar static int conn_id = 1; 8342654012fSReza Sabdar ndmpd_session_t session; 8352654012fSReza Sabdar ndmp_notify_connected_request req; 8362654012fSReza Sabdar int connection_fd; 8372654012fSReza Sabdar 8382654012fSReza Sabdar (void) memset(&session, 0, sizeof (session)); 8392654012fSReza Sabdar session.ns_connection = connection; 8402654012fSReza Sabdar session.ns_eof = FALSE; 8412654012fSReza Sabdar /* 8422654012fSReza Sabdar * The 'protocol_version' must be 1 at first, since the client talks 8432654012fSReza Sabdar * to the server in version 1 then they can move to a higher 8442654012fSReza Sabdar * protocol version. 8452654012fSReza Sabdar */ 8462654012fSReza Sabdar session.ns_protocol_version = ndmp_ver; 8472654012fSReza Sabdar 8482654012fSReza Sabdar session.ns_scsi.sd_is_open = -1; 8492654012fSReza Sabdar session.ns_scsi.sd_devid = -1; 8502654012fSReza Sabdar 8512654012fSReza Sabdar session.ns_scsi.sd_sid = 0; 8522654012fSReza Sabdar session.ns_scsi.sd_lun = 0; 8532654012fSReza Sabdar session.ns_scsi.sd_valid_target_set = 0; 8542654012fSReza Sabdar (void) memset(session.ns_scsi.sd_adapter_name, 0, 8552654012fSReza Sabdar sizeof (session.ns_scsi.sd_adapter_name)); 8562654012fSReza Sabdar 8572654012fSReza Sabdar session.ns_tape.td_fd = -1; 8582654012fSReza Sabdar session.ns_tape.td_sid = 0; 8592654012fSReza Sabdar session.ns_tape.td_lun = 0; 8602654012fSReza Sabdar (void) memset(session.ns_tape.td_adapter_name, 0, 8612654012fSReza Sabdar sizeof (session.ns_tape.td_adapter_name)); 8622654012fSReza Sabdar session.ns_tape.td_pos = 0; 8632654012fSReza Sabdar session.ns_tape.td_record_count = 0; 8642654012fSReza Sabdar session.ns_file_handler_list = 0; 8652654012fSReza Sabdar 8662654012fSReza Sabdar (void) ndmpd_data_init(&session); 8672654012fSReza Sabdar ndmpd_file_history_init(&session); 8682654012fSReza Sabdar if (ndmpd_mover_init(&session) < 0) 8692654012fSReza Sabdar return; 8702654012fSReza Sabdar 8712654012fSReza Sabdar if (ndmp_lbr_init(&session) < 0) 8722654012fSReza Sabdar return; 8732654012fSReza Sabdar 8742654012fSReza Sabdar /* 8752654012fSReza Sabdar * Setup defaults here. The init functions can not set defaults 8762654012fSReza Sabdar * since the init functions are called by the stop request handlers 8772654012fSReza Sabdar * and client set variables need to persist across data operations. 8782654012fSReza Sabdar */ 8792654012fSReza Sabdar session.ns_mover.md_record_size = MAX_RECORD_SIZE; 8802654012fSReza Sabdar 8812654012fSReza Sabdar ndmp_set_client_data(connection, (void *)&session); 8822654012fSReza Sabdar 8832654012fSReza Sabdar req.reason = NDMP_CONNECTED; 8842654012fSReza Sabdar req.protocol_version = ndmp_ver; 8852654012fSReza Sabdar req.text_reason = ""; 8862654012fSReza Sabdar 8877bc22e45SReza Sabdar if (ndmp_send_request_lock(connection, NDMP_NOTIFY_CONNECTION_STATUS, 8882654012fSReza Sabdar NDMP_NO_ERR, (void *)&req, 0) < 0) { 8892654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Connection terminated"); 8902654012fSReza Sabdar return; 8912654012fSReza Sabdar } 8922654012fSReza Sabdar connection_fd = ndmp_get_fd(connection); 8932654012fSReza Sabdar 8942654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "connection_fd: %d", connection_fd); 8952654012fSReza Sabdar 8962654012fSReza Sabdar /* 8972654012fSReza Sabdar * Add the handler function for the connection to the DMA. 8982654012fSReza Sabdar */ 8992654012fSReza Sabdar if (ndmpd_add_file_handler(&session, (void *)&session, connection_fd, 9002654012fSReza Sabdar NDMPD_SELECT_MODE_READ, HC_CLIENT, connection_file_handler) != 0) { 9012654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Could not register session handler."); 9022654012fSReza Sabdar return; 9032654012fSReza Sabdar } 9042654012fSReza Sabdar 9052654012fSReza Sabdar /* 9062654012fSReza Sabdar * Register the connection in the list of active connections. 9072654012fSReza Sabdar */ 9082654012fSReza Sabdar if (ndmp_connect_list_add(connection, &conn_id) != 0) { 9092654012fSReza Sabdar NDMP_LOG(LOG_ERR, 9102654012fSReza Sabdar "Could not register the session to the server."); 9112654012fSReza Sabdar (void) ndmpd_remove_file_handler(&session, connection_fd); 9122654012fSReza Sabdar return; 9132654012fSReza Sabdar } 9142654012fSReza Sabdar 9152654012fSReza Sabdar session.hardlink_q = hardlink_q_init(); 9162654012fSReza Sabdar 9172654012fSReza Sabdar while (session.ns_eof == FALSE) 9182654012fSReza Sabdar (void) ndmpd_select(&session, TRUE, HC_ALL); 9192654012fSReza Sabdar 9202654012fSReza Sabdar hardlink_q_cleanup(session.hardlink_q); 9212654012fSReza Sabdar 9222654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Connection terminated"); 9232654012fSReza Sabdar 9242654012fSReza Sabdar (void) ndmpd_remove_file_handler(&session, connection_fd); 9252654012fSReza Sabdar 9262654012fSReza Sabdar if (session.ns_scsi.sd_is_open != -1) { 9272654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "scsi.is_open: %d", 9282654012fSReza Sabdar session.ns_scsi.sd_is_open); 9292654012fSReza Sabdar (void) ndmp_open_list_del(session.ns_scsi.sd_adapter_name, 9302654012fSReza Sabdar session.ns_scsi.sd_sid, session.ns_scsi.sd_lun); 9312654012fSReza Sabdar } 9322654012fSReza Sabdar if (session.ns_tape.td_fd != -1) { 9332654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "tape.fd: %d", session.ns_tape.td_fd); 9342654012fSReza Sabdar (void) close(session.ns_tape.td_fd); 9352654012fSReza Sabdar (void) ndmp_open_list_del(session.ns_tape.td_adapter_name, 9362654012fSReza Sabdar session.ns_tape.td_sid, session.ns_tape.td_lun); 9372654012fSReza Sabdar } 9382654012fSReza Sabdar ndmpd_mover_shut_down(&session); 9392654012fSReza Sabdar ndmp_lbr_cleanup(&session); 9402654012fSReza Sabdar ndmpd_data_cleanup(&session); 9412654012fSReza Sabdar ndmpd_file_history_cleanup(&session, FALSE); 9422654012fSReza Sabdar ndmpd_mover_cleanup(&session); 9432654012fSReza Sabdar 9442654012fSReza Sabdar (void) ndmp_connect_list_del(connection); 9452654012fSReza Sabdar } 9462654012fSReza Sabdar 9472654012fSReza Sabdar 9482654012fSReza Sabdar /* 9492654012fSReza Sabdar * connection_file_handler 9502654012fSReza Sabdar * 9512654012fSReza Sabdar * ndmp_connection_t file handler function. 9522654012fSReza Sabdar * Called by ndmpd_select when data is available to be read on the 9532654012fSReza Sabdar * NDMP connection. 9542654012fSReza Sabdar * 9552654012fSReza Sabdar * Parameters: 9562654012fSReza Sabdar * cookie (input) - session pointer. 9572654012fSReza Sabdar * fd (input) - connection file descriptor. 9582654012fSReza Sabdar * mode (input) - select mode. 9592654012fSReza Sabdar * 9602654012fSReza Sabdar * Returns: 9612654012fSReza Sabdar * void. 9622654012fSReza Sabdar */ 9632654012fSReza Sabdar /*ARGSUSED*/ 9642654012fSReza Sabdar static void 9652654012fSReza Sabdar connection_file_handler(void *cookie, int fd, ulong_t mode) 9662654012fSReza Sabdar { 9672654012fSReza Sabdar ndmpd_session_t *session = (ndmpd_session_t *)cookie; 9682654012fSReza Sabdar 9692654012fSReza Sabdar if (ndmp_process_requests(session->ns_connection) < 0) 9702654012fSReza Sabdar session->ns_eof = TRUE; 9712654012fSReza Sabdar } 9722654012fSReza Sabdar 9732654012fSReza Sabdar 9742654012fSReza Sabdar /* ************* private functions *************************************** */ 9752654012fSReza Sabdar 9762654012fSReza Sabdar /* 9772654012fSReza Sabdar * ndmp_readit 9782654012fSReza Sabdar * 9792654012fSReza Sabdar * Low level read routine called by the xdrrec library. 9802654012fSReza Sabdar * 9812654012fSReza Sabdar * Parameters: 9822654012fSReza Sabdar * connection (input) - connection pointer. 9832654012fSReza Sabdar * buf (input) - location to store received data. 9842654012fSReza Sabdar * len (input) - max number of bytes to read. 9852654012fSReza Sabdar * 9862654012fSReza Sabdar * Returns: 9872654012fSReza Sabdar * >0 - number of bytes received. 9882654012fSReza Sabdar * -1 - error. 9892654012fSReza Sabdar */ 9902654012fSReza Sabdar static int 9912654012fSReza Sabdar ndmp_readit(void *connection_handle, caddr_t buf, int len) 9922654012fSReza Sabdar { 9932654012fSReza Sabdar ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 9942654012fSReza Sabdar 9952654012fSReza Sabdar len = read(connection->conn_sock, buf, len); 9962654012fSReza Sabdar if (len <= 0) { 9972654012fSReza Sabdar /* ndmp_connection_t has been closed. */ 9982654012fSReza Sabdar connection->conn_eof = TRUE; 9992654012fSReza Sabdar return (-1); 10002654012fSReza Sabdar } 10012654012fSReza Sabdar return (len); 10022654012fSReza Sabdar } 10032654012fSReza Sabdar 10042654012fSReza Sabdar /* 10052654012fSReza Sabdar * ndmp_writeit 10062654012fSReza Sabdar * 10072654012fSReza Sabdar * Low level write routine called by the xdrrec library. 10082654012fSReza Sabdar * 10092654012fSReza Sabdar * Parameters: 10102654012fSReza Sabdar * connection (input) - connection pointer. 10112654012fSReza Sabdar * buf (input) - location to store received data. 10122654012fSReza Sabdar * len (input) - max number of bytes to read. 10132654012fSReza Sabdar * 10142654012fSReza Sabdar * Returns: 10152654012fSReza Sabdar * >0 - number of bytes sent. 10162654012fSReza Sabdar * -1 - error. 10172654012fSReza Sabdar */ 10182654012fSReza Sabdar static int 10192654012fSReza Sabdar ndmp_writeit(void *connection_handle, caddr_t buf, int len) 10202654012fSReza Sabdar { 10212654012fSReza Sabdar ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 10222654012fSReza Sabdar register int n; 10232654012fSReza Sabdar register int cnt; 10242654012fSReza Sabdar 10252654012fSReza Sabdar for (cnt = len; cnt > 0; cnt -= n, buf += n) { 10262654012fSReza Sabdar if ((n = write(connection->conn_sock, buf, cnt)) < 0) { 10272654012fSReza Sabdar connection->conn_eof = TRUE; 10282654012fSReza Sabdar return (-1); 10292654012fSReza Sabdar } 10302654012fSReza Sabdar } 10312654012fSReza Sabdar 10322654012fSReza Sabdar return (len); 10332654012fSReza Sabdar } 10342654012fSReza Sabdar 10352654012fSReza Sabdar 10362654012fSReza Sabdar /* 10372654012fSReza Sabdar * ndmp_recv_msg 10382654012fSReza Sabdar * 10392654012fSReza Sabdar * Read the next message. 10402654012fSReza Sabdar * 10412654012fSReza Sabdar * Parameters: 10422654012fSReza Sabdar * connection (input) - connection pointer. 10432654012fSReza Sabdar * msg (output) - received message. 10442654012fSReza Sabdar * 10452654012fSReza Sabdar * Returns: 10462654012fSReza Sabdar * 0 - Message successfully received. 10472654012fSReza Sabdar * error number - Message related error. 10482654012fSReza Sabdar * -1 - Error decoding the message header. 10492654012fSReza Sabdar */ 10502654012fSReza Sabdar static int 10512654012fSReza Sabdar ndmp_recv_msg(ndmp_connection_t *connection) 10522654012fSReza Sabdar { 10532654012fSReza Sabdar bool_t(*xdr_func) (XDR *, ...) = NULL; 10542654012fSReza Sabdar 10552654012fSReza Sabdar /* Decode the header. */ 10562654012fSReza Sabdar connection->conn_xdrs.x_op = XDR_DECODE; 10572654012fSReza Sabdar (void) xdrrec_skiprecord(&connection->conn_xdrs); 10582654012fSReza Sabdar if (!xdr_ndmp_header(&connection->conn_xdrs, 10592654012fSReza Sabdar &connection->conn_msginfo.mi_hdr)) 10602654012fSReza Sabdar return (-1); 10612654012fSReza Sabdar 10622654012fSReza Sabdar /* Lookup info necessary for processing this message. */ 10632654012fSReza Sabdar if ((connection->conn_msginfo.mi_handler = ndmp_get_handler(connection, 10642654012fSReza Sabdar connection->conn_msginfo.mi_hdr.message)) == 0) { 10652654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Message 0x%x not supported", 10662654012fSReza Sabdar connection->conn_msginfo.mi_hdr.message); 10672654012fSReza Sabdar return (NDMP_NOT_SUPPORTED_ERR); 10682654012fSReza Sabdar } 10692654012fSReza Sabdar connection->conn_msginfo.mi_body = 0; 10702654012fSReza Sabdar 10712654012fSReza Sabdar if (connection->conn_msginfo.mi_hdr.error != NDMP_NO_ERR) 10722654012fSReza Sabdar return (0); 10732654012fSReza Sabdar 10742654012fSReza Sabdar /* Determine body type */ 10752654012fSReza Sabdar if (connection->conn_msginfo.mi_hdr.message_type == 10762654012fSReza Sabdar NDMP_MESSAGE_REQUEST) { 10772654012fSReza Sabdar if (ndmp_check_auth_required( 10782654012fSReza Sabdar connection->conn_msginfo.mi_hdr.message) && 10792654012fSReza Sabdar !connection->conn_authorized) { 10802654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 10812654012fSReza Sabdar "Processing request 0x%x:connection not authorized", 10822654012fSReza Sabdar connection->conn_msginfo.mi_hdr.message); 10832654012fSReza Sabdar return (NDMP_NOT_AUTHORIZED_ERR); 10842654012fSReza Sabdar } 10852654012fSReza Sabdar if (connection->conn_msginfo.mi_handler->mh_sizeof_request > 10862654012fSReza Sabdar 0) { 10872654012fSReza Sabdar xdr_func = 10882654012fSReza Sabdar connection->conn_msginfo.mi_handler->mh_xdr_request; 10892654012fSReza Sabdar if (xdr_func == NULL) { 10902654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 10912654012fSReza Sabdar "Processing request 0x%x: no xdr function " 10922654012fSReza Sabdar "in handler table", 10932654012fSReza Sabdar connection->conn_msginfo.mi_hdr.message); 10942654012fSReza Sabdar return (NDMP_NOT_SUPPORTED_ERR); 10952654012fSReza Sabdar } 10962654012fSReza Sabdar connection->conn_msginfo.mi_body = ndmp_malloc( 10972654012fSReza Sabdar connection->conn_msginfo.mi_handler-> 10982654012fSReza Sabdar mh_sizeof_request); 10992654012fSReza Sabdar if (connection->conn_msginfo.mi_body == NULL) 11002654012fSReza Sabdar return (NDMP_NO_MEM_ERR); 11012654012fSReza Sabdar 11022654012fSReza Sabdar (void) memset(connection->conn_msginfo.mi_body, 0, 11032654012fSReza Sabdar connection->conn_msginfo.mi_handler-> 11042654012fSReza Sabdar mh_sizeof_request); 11052654012fSReza Sabdar } 11062654012fSReza Sabdar } else { 11072654012fSReza Sabdar if (connection->conn_msginfo.mi_handler->mh_sizeof_reply > 0) { 11082654012fSReza Sabdar xdr_func = 11092654012fSReza Sabdar connection->conn_msginfo.mi_handler->mh_xdr_reply; 11102654012fSReza Sabdar if (xdr_func == NULL) { 11112654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 11122654012fSReza Sabdar "Processing reply 0x%x: no xdr function " 11132654012fSReza Sabdar "in handler table", 11142654012fSReza Sabdar connection->conn_msginfo.mi_hdr.message); 11152654012fSReza Sabdar return (NDMP_NOT_SUPPORTED_ERR); 11162654012fSReza Sabdar } 11172654012fSReza Sabdar connection->conn_msginfo.mi_body = ndmp_malloc( 11182654012fSReza Sabdar connection->conn_msginfo.mi_handler-> 11192654012fSReza Sabdar mh_sizeof_reply); 11202654012fSReza Sabdar if (connection->conn_msginfo.mi_body == NULL) 11212654012fSReza Sabdar return (NDMP_NO_MEM_ERR); 11222654012fSReza Sabdar 11232654012fSReza Sabdar (void) memset(connection->conn_msginfo.mi_body, 0, 11242654012fSReza Sabdar connection->conn_msginfo.mi_handler-> 11252654012fSReza Sabdar mh_sizeof_reply); 11262654012fSReza Sabdar } 11272654012fSReza Sabdar } 11282654012fSReza Sabdar 11292654012fSReza Sabdar /* Decode message arguments if needed */ 11302654012fSReza Sabdar if (xdr_func) { 11312654012fSReza Sabdar if (!(*xdr_func)(&connection->conn_xdrs, 11322654012fSReza Sabdar connection->conn_msginfo.mi_body)) { 11332654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 11342654012fSReza Sabdar "Processing message 0x%x: error decoding arguments", 11352654012fSReza Sabdar connection->conn_msginfo.mi_hdr.message); 11362654012fSReza Sabdar free(connection->conn_msginfo.mi_body); 11372654012fSReza Sabdar connection->conn_msginfo.mi_body = 0; 11382654012fSReza Sabdar return (NDMP_XDR_DECODE_ERR); 11392654012fSReza Sabdar } 11402654012fSReza Sabdar } 11412654012fSReza Sabdar return (0); 11422654012fSReza Sabdar } 11432654012fSReza Sabdar 11442654012fSReza Sabdar /* 11452654012fSReza Sabdar * ndmp_process_messages 11462654012fSReza Sabdar * 11472654012fSReza Sabdar * Reads the next message into the stream buffer. 11482654012fSReza Sabdar * Processes messages until the stream buffer is empty. 11492654012fSReza Sabdar * 11502654012fSReza Sabdar * This function processes all data in the stream buffer before returning. 11512654012fSReza Sabdar * This allows functions like poll() to be used to determine when new 11522654012fSReza Sabdar * messages have arrived. If only some of the messages in the stream buffer 11532654012fSReza Sabdar * were processed and then poll was called, poll() could block waiting for 11542654012fSReza Sabdar * a message that had already been received and read into the stream buffer. 11552654012fSReza Sabdar * 11562654012fSReza Sabdar * This function processes both request and reply messages. 11572654012fSReza Sabdar * Request messages are dispatched using the appropriate function from the 11582654012fSReza Sabdar * message handling table. 11592654012fSReza Sabdar * Only one reply messages may be pending receipt at a time. 11602654012fSReza Sabdar * A reply message, if received, is placed in connection->conn_msginfo 11612654012fSReza Sabdar * before returning to the caller. 11622654012fSReza Sabdar * Errors are reported if a reply is received but not expected or if 11632654012fSReza Sabdar * more than one reply message is received 11642654012fSReza Sabdar * 11652654012fSReza Sabdar * Parameters: 11662654012fSReza Sabdar * connection (input) - connection pointer. 11672654012fSReza Sabdar * reply_expected (output) - TRUE - a reply message is expected. 11682654012fSReza Sabdar * FALSE - no reply message is expected and 11692654012fSReza Sabdar * an error will be reported if a reply 11702654012fSReza Sabdar * is received. 11712654012fSReza Sabdar * 11722654012fSReza Sabdar * Returns: 11732654012fSReza Sabdar * NDMP_PROC_REP_ERR - 1 or more messages successfully processed, 11742654012fSReza Sabdar * error processing reply message. 11752654012fSReza Sabdar * NDMP_PROC_REP_ERR - 1 or more messages successfully processed, 11762654012fSReza Sabdar * reply seen. 11772654012fSReza Sabdar * NDMP_PROC_REP_ERR - 1 or more messages successfully processed, 11782654012fSReza Sabdar * no reply seen. 11792654012fSReza Sabdar * NDMP_PROC_REP_ERR - error; connection no longer established. 11802654012fSReza Sabdar * 11812654012fSReza Sabdar * Notes: 11822654012fSReza Sabdar * If the peer is generating a large number of requests, a caller 11832654012fSReza Sabdar * looking for a reply will be blocked while the requests are handled. 11842654012fSReza Sabdar * This is because this function does not return until the stream 11852654012fSReza Sabdar * buffer is empty. 11862654012fSReza Sabdar * Code needs to be added to allow a return if the stream buffer 11872654012fSReza Sabdar * is not empty but there is data available on the socket. This will 11882654012fSReza Sabdar * prevent poll() from blocking and prevent a caller looking for a reply 11892654012fSReza Sabdar * from getting blocked by a bunch of requests. 11902654012fSReza Sabdar */ 11912654012fSReza Sabdar static int 11922654012fSReza Sabdar ndmp_process_messages(ndmp_connection_t *connection, boolean_t reply_expected) 11932654012fSReza Sabdar { 11942654012fSReza Sabdar msg_info_t reply_msginfo; 11952654012fSReza Sabdar boolean_t reply_read = FALSE; 11962654012fSReza Sabdar boolean_t reply_error = FALSE; 11972654012fSReza Sabdar int err; 11982654012fSReza Sabdar 11992654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "reply_expected: %s", 12002654012fSReza Sabdar reply_expected == TRUE ? "TRUE" : "FALSE"); 12012654012fSReza Sabdar 12022654012fSReza Sabdar (void) memset((void *)&reply_msginfo, 0, sizeof (msg_info_t)); 12032654012fSReza Sabdar 12042654012fSReza Sabdar do { 12052654012fSReza Sabdar (void) memset((void *)&connection->conn_msginfo, 0, 12062654012fSReza Sabdar sizeof (msg_info_t)); 12072654012fSReza Sabdar 12082654012fSReza Sabdar if ((err = ndmp_recv_msg(connection)) != NDMP_NO_ERR) { 12092654012fSReza Sabdar if (connection->conn_eof) { 12102654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "detected eof"); 12112654012fSReza Sabdar return (NDMP_PROC_ERR); 12122654012fSReza Sabdar } 12132654012fSReza Sabdar if (err < 1) { 12142654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "error decoding header"); 12152654012fSReza Sabdar 12162654012fSReza Sabdar /* 12172654012fSReza Sabdar * Error occurred decoding the header. 12182654012fSReza Sabdar * Don't send a reply since we don't know 12192654012fSReza Sabdar * the message or if the message was even 12202654012fSReza Sabdar * a request message. To be safe, assume 12212654012fSReza Sabdar * that the message was a reply if a reply 12222654012fSReza Sabdar * was expected. Need to do this to prevent 12232654012fSReza Sabdar * hanging ndmp_send_request() waiting for a 12242654012fSReza Sabdar * reply. Don't set reply_read so that the 12252654012fSReza Sabdar * reply will be processed if it is received 12262654012fSReza Sabdar * later. 12272654012fSReza Sabdar */ 12282654012fSReza Sabdar if (reply_read == FALSE) 12292654012fSReza Sabdar reply_error = TRUE; 12302654012fSReza Sabdar 12312654012fSReza Sabdar continue; 12322654012fSReza Sabdar } 12332654012fSReza Sabdar if (connection->conn_msginfo.mi_hdr.message_type 12342654012fSReza Sabdar != NDMP_MESSAGE_REQUEST) { 12352654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "received reply: 0x%x", 12362654012fSReza Sabdar connection->conn_msginfo.mi_hdr.message); 12372654012fSReza Sabdar 12382654012fSReza Sabdar if (reply_expected == FALSE || 12392654012fSReza Sabdar reply_read == TRUE) 12402654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 12412654012fSReza Sabdar "Unexpected reply message: 0x%x", 12422654012fSReza Sabdar connection->conn_msginfo.mi_hdr. 12432654012fSReza Sabdar message); 12442654012fSReza Sabdar 12452654012fSReza Sabdar ndmp_free_message((ndmp_connection_t *) 12462654012fSReza Sabdar connection); 12472654012fSReza Sabdar 12482654012fSReza Sabdar if (reply_read == FALSE) { 12492654012fSReza Sabdar reply_read = TRUE; 12502654012fSReza Sabdar reply_error = TRUE; 12512654012fSReza Sabdar } 12522654012fSReza Sabdar continue; 12532654012fSReza Sabdar } 12542654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "received request: 0x%x", 12552654012fSReza Sabdar connection->conn_msginfo.mi_hdr.message); 12562654012fSReza Sabdar 12572654012fSReza Sabdar (void) ndmp_send_response((ndmp_connection_t *) 12582654012fSReza Sabdar connection, err, NULL); 12592654012fSReza Sabdar ndmp_free_message((ndmp_connection_t *)connection); 12602654012fSReza Sabdar continue; 12612654012fSReza Sabdar } 12622654012fSReza Sabdar if (connection->conn_msginfo.mi_hdr.message_type 12632654012fSReza Sabdar != NDMP_MESSAGE_REQUEST) { 12642654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "received reply: 0x%x", 12652654012fSReza Sabdar connection->conn_msginfo.mi_hdr.message); 12662654012fSReza Sabdar 12672654012fSReza Sabdar if (reply_expected == FALSE || reply_read == TRUE) { 12682654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 12692654012fSReza Sabdar "Unexpected reply message: 0x%x", 12702654012fSReza Sabdar connection->conn_msginfo.mi_hdr.message); 12712654012fSReza Sabdar ndmp_free_message((ndmp_connection_t *) 12722654012fSReza Sabdar connection); 12732654012fSReza Sabdar continue; 12742654012fSReza Sabdar } 12752654012fSReza Sabdar reply_read = TRUE; 12762654012fSReza Sabdar reply_msginfo = connection->conn_msginfo; 12772654012fSReza Sabdar continue; 12782654012fSReza Sabdar } 12792654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "received request: 0x%x", 12802654012fSReza Sabdar connection->conn_msginfo.mi_hdr.message); 12812654012fSReza Sabdar 12822654012fSReza Sabdar /* 12832654012fSReza Sabdar * The following is needed to catch an improperly constructed 12842654012fSReza Sabdar * handler table or to deal with an NDMP client that is not 12852654012fSReza Sabdar * conforming to the negotiated protocol version. 12862654012fSReza Sabdar */ 12872654012fSReza Sabdar if (connection->conn_msginfo.mi_handler->mh_func == NULL) { 12882654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "No handler for message 0x%x", 12892654012fSReza Sabdar connection->conn_msginfo.mi_hdr.message); 12902654012fSReza Sabdar 12912654012fSReza Sabdar (void) ndmp_send_response((ndmp_connection_t *) 12922654012fSReza Sabdar connection, NDMP_NOT_SUPPORTED_ERR, NULL); 12932654012fSReza Sabdar ndmp_free_message((ndmp_connection_t *)connection); 12942654012fSReza Sabdar continue; 12952654012fSReza Sabdar } 12962654012fSReza Sabdar /* 12972654012fSReza Sabdar * Call the handler function. 12982654012fSReza Sabdar * The handler will send any necessary reply. 12992654012fSReza Sabdar */ 13002654012fSReza Sabdar (*connection->conn_msginfo.mi_handler->mh_func) (connection, 13012654012fSReza Sabdar connection->conn_msginfo.mi_body); 13022654012fSReza Sabdar 13032654012fSReza Sabdar ndmp_free_message((ndmp_connection_t *)connection); 13042654012fSReza Sabdar 13052654012fSReza Sabdar } while (xdrrec_eof(&connection->conn_xdrs) == FALSE && 13062654012fSReza Sabdar connection->conn_eof == FALSE); 13072654012fSReza Sabdar 13082654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "no more messages in stream buffer"); 13092654012fSReza Sabdar 13102654012fSReza Sabdar if (connection->conn_eof == TRUE) { 13112654012fSReza Sabdar if (reply_msginfo.mi_body) 13122654012fSReza Sabdar free(reply_msginfo.mi_body); 13132654012fSReza Sabdar return (NDMP_PROC_ERR); 13142654012fSReza Sabdar } 13152654012fSReza Sabdar if (reply_error) { 13162654012fSReza Sabdar if (reply_msginfo.mi_body) 13172654012fSReza Sabdar free(reply_msginfo.mi_body); 13182654012fSReza Sabdar return (NDMP_PROC_REP_ERR); 13192654012fSReza Sabdar } 13202654012fSReza Sabdar if (reply_read) { 13212654012fSReza Sabdar connection->conn_msginfo = reply_msginfo; 13222654012fSReza Sabdar return (NDMP_PROC_MSG); 13232654012fSReza Sabdar } 13242654012fSReza Sabdar return (NDMP_PROC_REP); 13252654012fSReza Sabdar } 13262654012fSReza Sabdar 13272654012fSReza Sabdar 13282654012fSReza Sabdar /* 13292654012fSReza Sabdar * ndmp_get_interface 13302654012fSReza Sabdar * 13312654012fSReza Sabdar * Return the NDMP interface (e.g. config, scsi, tape) for the 13322654012fSReza Sabdar * specific message. 13332654012fSReza Sabdar * 13342654012fSReza Sabdar * Parameters: 13352654012fSReza Sabdar * message (input) - message number. 13362654012fSReza Sabdar * 13372654012fSReza Sabdar * Returns: 13382654012fSReza Sabdar * NULL - message not found. 13392654012fSReza Sabdar * pointer to handler info. 13402654012fSReza Sabdar */ 13412654012fSReza Sabdar static ndmp_handler_t * 13422654012fSReza Sabdar ndmp_get_interface(ndmp_message message) 13432654012fSReza Sabdar { 13442654012fSReza Sabdar ndmp_handler_t *ni = &ndmp_msghdl_tab[(message >> 8) % INT_MAXCMD]; 13452654012fSReza Sabdar 13462654012fSReza Sabdar if ((message & 0xff) >= ni->hd_cnt) 13472654012fSReza Sabdar return (NULL); 13482654012fSReza Sabdar 13492654012fSReza Sabdar /* Sanity check */ 13502654012fSReza Sabdar if (ni->hd_msgs[message & 0xff].hm_message != message) 13512654012fSReza Sabdar return (NULL); 13522654012fSReza Sabdar 13532654012fSReza Sabdar return (ni); 13542654012fSReza Sabdar } 13552654012fSReza Sabdar 13562654012fSReza Sabdar /* 13572654012fSReza Sabdar * ndmp_get_handler 13582654012fSReza Sabdar * 13592654012fSReza Sabdar * Return the handler info for the specified NDMP message. 13602654012fSReza Sabdar * 13612654012fSReza Sabdar * Parameters: 13622654012fSReza Sabdar * connection (input) - connection pointer. 13632654012fSReza Sabdar * message (input) - message number. 13642654012fSReza Sabdar * 13652654012fSReza Sabdar * Returns: 13662654012fSReza Sabdar * NULL - message not found. 13672654012fSReza Sabdar * pointer to handler info. 13682654012fSReza Sabdar */ 13692654012fSReza Sabdar static ndmp_msg_handler_t * 13702654012fSReza Sabdar ndmp_get_handler(ndmp_connection_t *connection, ndmp_message message) 13712654012fSReza Sabdar { 13722654012fSReza Sabdar ndmp_msg_handler_t *handler = NULL; 13732654012fSReza Sabdar 13742654012fSReza Sabdar ndmp_handler_t *ni = ndmp_get_interface(message); 13752654012fSReza Sabdar int ver = connection->conn_version; 13762654012fSReza Sabdar 13772654012fSReza Sabdar if (ni) 13782654012fSReza Sabdar handler = &ni->hd_msgs[message & 0xff].hm_msg_v[ver - 2]; 13792654012fSReza Sabdar 13802654012fSReza Sabdar return (handler); 13812654012fSReza Sabdar } 13822654012fSReza Sabdar 13832654012fSReza Sabdar /* 13842654012fSReza Sabdar * ndmp_check_auth_required 13852654012fSReza Sabdar * 13862654012fSReza Sabdar * Check if the connection needs to be authenticated before 13872654012fSReza Sabdar * this message is being processed. 13882654012fSReza Sabdar * 13892654012fSReza Sabdar * Parameters: 13902654012fSReza Sabdar * message (input) - message number. 13912654012fSReza Sabdar * 13922654012fSReza Sabdar * Returns: 13932654012fSReza Sabdar * TRUE - required 13942654012fSReza Sabdar * FALSE - not required 13952654012fSReza Sabdar */ 13962654012fSReza Sabdar static boolean_t 13972654012fSReza Sabdar ndmp_check_auth_required(ndmp_message message) 13982654012fSReza Sabdar { 13992654012fSReza Sabdar boolean_t auth_req = FALSE; 14002654012fSReza Sabdar ndmp_handler_t *ni = ndmp_get_interface(message); 14012654012fSReza Sabdar 14022654012fSReza Sabdar if (ni) 14032654012fSReza Sabdar auth_req = ni->hd_msgs[message & 0xff].hm_auth_required; 14042654012fSReza Sabdar 14052654012fSReza Sabdar return (auth_req); 14062654012fSReza Sabdar } 14072654012fSReza Sabdar 14082654012fSReza Sabdar /* 14092654012fSReza Sabdar * tcp_accept 14102654012fSReza Sabdar * 14112654012fSReza Sabdar * A wrapper around accept for retrying and getting the IP address 14122654012fSReza Sabdar * 14132654012fSReza Sabdar * Parameters: 14142654012fSReza Sabdar * listen_sock (input) - the socket for listening 14152654012fSReza Sabdar * inaddr_p (output) - the IP address of peer connection 14162654012fSReza Sabdar * 14172654012fSReza Sabdar * Returns: 14182654012fSReza Sabdar * socket for the accepted connection 14192654012fSReza Sabdar * -1: error 14202654012fSReza Sabdar */ 14212654012fSReza Sabdar int 14222654012fSReza Sabdar tcp_accept(int listen_sock, unsigned int *inaddr_p) 14232654012fSReza Sabdar { 14242654012fSReza Sabdar struct sockaddr_in sin; 14252654012fSReza Sabdar int sock, i; 14262654012fSReza Sabdar int try; 14272654012fSReza Sabdar 14282654012fSReza Sabdar for (try = 0; try < 3; try++) { 14292654012fSReza Sabdar i = sizeof (sin); 14302654012fSReza Sabdar sock = accept(listen_sock, (struct sockaddr *)&sin, &i); 14312654012fSReza Sabdar if (sock < 0) { 14322654012fSReza Sabdar continue; 14332654012fSReza Sabdar } 14342654012fSReza Sabdar *inaddr_p = sin.sin_addr.s_addr; 14352654012fSReza Sabdar return (sock); 14362654012fSReza Sabdar } 14372654012fSReza Sabdar return (-1); 14382654012fSReza Sabdar } 14392654012fSReza Sabdar 14402654012fSReza Sabdar 14412654012fSReza Sabdar /* 14422654012fSReza Sabdar * tcp_get_peer 14432654012fSReza Sabdar * 14442654012fSReza Sabdar * Get the peer IP address for a connection 14452654012fSReza Sabdar * 14462654012fSReza Sabdar * Parameters: 14472654012fSReza Sabdar * sock (input) - the active socket 14482654012fSReza Sabdar * inaddr_p (output) - the IP address of peer connection 14492654012fSReza Sabdar * port_p (output) - the port number of peer connection 14502654012fSReza Sabdar * 14512654012fSReza Sabdar * Returns: 14522654012fSReza Sabdar * socket for the accepted connection 14532654012fSReza Sabdar * -1: error 14542654012fSReza Sabdar */ 14552654012fSReza Sabdar int 14562654012fSReza Sabdar tcp_get_peer(int sock, unsigned int *inaddr_p, int *port_p) 14572654012fSReza Sabdar { 14582654012fSReza Sabdar struct sockaddr_in sin; 14592654012fSReza Sabdar int i, rc; 14602654012fSReza Sabdar 14612654012fSReza Sabdar i = sizeof (sin); 14622654012fSReza Sabdar rc = getpeername(sock, (struct sockaddr *)&sin, &i); 14632654012fSReza Sabdar if (rc != 0) 14642654012fSReza Sabdar return (-1); 14652654012fSReza Sabdar 14662654012fSReza Sabdar if (inaddr_p) 14672654012fSReza Sabdar *inaddr_p = sin.sin_addr.s_addr; 14682654012fSReza Sabdar 14692654012fSReza Sabdar if (port_p) 14702654012fSReza Sabdar *port_p = ntohs(sin.sin_port); 14712654012fSReza Sabdar 14722654012fSReza Sabdar return (sock); 14732654012fSReza Sabdar 14742654012fSReza Sabdar } 14752654012fSReza Sabdar 14762654012fSReza Sabdar /* 14772654012fSReza Sabdar * gethostaddr 14782654012fSReza Sabdar * 14792654012fSReza Sabdar * Get the IP address string of the current host 14802654012fSReza Sabdar * 14812654012fSReza Sabdar * Parameters: 14822654012fSReza Sabdar * void 14832654012fSReza Sabdar * 14842654012fSReza Sabdar * Returns: 14852654012fSReza Sabdar * IP address 14862654012fSReza Sabdar * NULL: error 14872654012fSReza Sabdar */ 14882654012fSReza Sabdar char * 14892654012fSReza Sabdar gethostaddr(void) 14902654012fSReza Sabdar { 14912654012fSReza Sabdar static char s[MAXHOSTNAMELEN]; 14922654012fSReza Sabdar struct hostent *h; 14932654012fSReza Sabdar struct in_addr in; 14942654012fSReza Sabdar char *p; 14952654012fSReza Sabdar 14962654012fSReza Sabdar if (gethostname(s, sizeof (s)) == -1) 14972654012fSReza Sabdar return (NULL); 14982654012fSReza Sabdar 14992654012fSReza Sabdar if ((h = gethostbyname(s)) == NULL) 15002654012fSReza Sabdar return (NULL); 15012654012fSReza Sabdar 15022654012fSReza Sabdar p = h->h_addr_list[0]; 15032654012fSReza Sabdar (void) memcpy(&in.s_addr, p, sizeof (in.s_addr)); 15042654012fSReza Sabdar return (inet_ntoa(in)); 15052654012fSReza Sabdar } 15062654012fSReza Sabdar 15072654012fSReza Sabdar /* 15082654012fSReza Sabdar * ndmpd_audit_backup 15092654012fSReza Sabdar * 15102654012fSReza Sabdar * Generate AUE_ndmp_backup audit record 15112654012fSReza Sabdar */ 15122654012fSReza Sabdar /*ARGSUSED*/ 15132654012fSReza Sabdar void 15142654012fSReza Sabdar ndmpd_audit_backup(ndmp_connection_t *conn, 15152654012fSReza Sabdar char *path, int dest, char *local_path, int result) 15162654012fSReza Sabdar { 15172654012fSReza Sabdar adt_event_data_t *event; 15182654012fSReza Sabdar 15192654012fSReza Sabdar if ((event = adt_alloc_event(conn->conn_ah, ADT_ndmp_backup)) == NULL) { 15202654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Audit failure: %m."); 15212654012fSReza Sabdar return; 15222654012fSReza Sabdar } 15232654012fSReza Sabdar event->adt_ndmp_backup.source = path; 15242654012fSReza Sabdar 15252654012fSReza Sabdar if (dest == NDMP_ADDR_LOCAL) { 15262654012fSReza Sabdar event->adt_ndmp_backup.local_dest = local_path; 15272654012fSReza Sabdar } else { 15282654012fSReza Sabdar event->adt_ndmp_backup.remote_dest = conn->conn_sock; 15292654012fSReza Sabdar } 15302654012fSReza Sabdar 15312654012fSReza Sabdar if (result == 0) { 15322654012fSReza Sabdar if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) 15332654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Audit failure: %m."); 15342654012fSReza Sabdar } else { 15352654012fSReza Sabdar if (adt_put_event(event, ADT_FAILURE, result) != 0) 15362654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Audit failure: %m."); 15372654012fSReza Sabdar } 15382654012fSReza Sabdar 15392654012fSReza Sabdar adt_free_event(event); 15402654012fSReza Sabdar } 15412654012fSReza Sabdar 15422654012fSReza Sabdar 15432654012fSReza Sabdar /* 15442654012fSReza Sabdar * ndmpd_audit_restore 15452654012fSReza Sabdar * 15462654012fSReza Sabdar * Generate AUE_ndmp_restore audit record 15472654012fSReza Sabdar */ 15482654012fSReza Sabdar /*ARGSUSED*/ 15492654012fSReza Sabdar void 15502654012fSReza Sabdar ndmpd_audit_restore(ndmp_connection_t *conn, 15512654012fSReza Sabdar char *path, int dest, char *local_path, int result) 15522654012fSReza Sabdar { 15532654012fSReza Sabdar adt_event_data_t *event; 15542654012fSReza Sabdar 15552654012fSReza Sabdar if ((event = adt_alloc_event(conn->conn_ah, 15562654012fSReza Sabdar ADT_ndmp_restore)) == NULL) { 15572654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Audit failure: %m."); 15582654012fSReza Sabdar return; 15592654012fSReza Sabdar } 15602654012fSReza Sabdar event->adt_ndmp_restore.destination = path; 15612654012fSReza Sabdar 15622654012fSReza Sabdar if (dest == NDMP_ADDR_LOCAL) { 15632654012fSReza Sabdar event->adt_ndmp_restore.local_source = local_path; 15642654012fSReza Sabdar } else { 15652654012fSReza Sabdar event->adt_ndmp_restore.remote_source = conn->conn_sock; 15662654012fSReza Sabdar } 15672654012fSReza Sabdar 15682654012fSReza Sabdar if (result == 0) { 15692654012fSReza Sabdar if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) 15702654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Audit failure: %m."); 15712654012fSReza Sabdar } else { 15722654012fSReza Sabdar if (adt_put_event(event, ADT_FAILURE, result) != 0) 15732654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Audit failure: %m."); 15742654012fSReza Sabdar } 15752654012fSReza Sabdar 15762654012fSReza Sabdar adt_free_event(event); 15772654012fSReza Sabdar } 15782654012fSReza Sabdar 15792654012fSReza Sabdar 15802654012fSReza Sabdar /* 15812654012fSReza Sabdar * ndmpd_audit_connect 15822654012fSReza Sabdar * 15832654012fSReza Sabdar * Generate AUE_ndmp_connect audit record 15842654012fSReza Sabdar */ 15852654012fSReza Sabdar /*ARGSUSED*/ 15862654012fSReza Sabdar void 15872654012fSReza Sabdar ndmpd_audit_connect(ndmp_connection_t *conn, int result) 15882654012fSReza Sabdar { 15892654012fSReza Sabdar adt_event_data_t *event; 15902654012fSReza Sabdar adt_termid_t *termid; 15912654012fSReza Sabdar 15922654012fSReza Sabdar if (adt_load_termid(conn->conn_sock, &termid) != 0) { 15932654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Audit failure: %m."); 15942654012fSReza Sabdar return; 15952654012fSReza Sabdar } 15962654012fSReza Sabdar 15972654012fSReza Sabdar if (adt_set_user(conn->conn_ah, ADT_NO_ATTRIB, ADT_NO_ATTRIB, 15982654012fSReza Sabdar ADT_NO_ATTRIB, ADT_NO_ATTRIB, termid, ADT_NEW) != 0) { 15992654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Audit failure: %m."); 16002654012fSReza Sabdar free(termid); 16012654012fSReza Sabdar return; 16022654012fSReza Sabdar } 16032654012fSReza Sabdar free(termid); 16042654012fSReza Sabdar 16052654012fSReza Sabdar if ((event = adt_alloc_event(conn->conn_ah, 16062654012fSReza Sabdar ADT_ndmp_connect)) == NULL) { 16072654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Audit failure: %m."); 16082654012fSReza Sabdar return; 16092654012fSReza Sabdar } 16102654012fSReza Sabdar 16112654012fSReza Sabdar if (result == 0) { 16122654012fSReza Sabdar if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) 16132654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Audit failure: %m."); 16142654012fSReza Sabdar } else { 16152654012fSReza Sabdar if (adt_put_event(event, ADT_FAILURE, result) != 0) 16162654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Audit failure: %m."); 16172654012fSReza Sabdar } 16182654012fSReza Sabdar 16192654012fSReza Sabdar adt_free_event(event); 16202654012fSReza Sabdar } 16212654012fSReza Sabdar 16222654012fSReza Sabdar 16232654012fSReza Sabdar /* 16242654012fSReza Sabdar * ndmpd_audit_disconnect 16252654012fSReza Sabdar * 16262654012fSReza Sabdar * Generate AUE_ndmp_disconnect audit record 16272654012fSReza Sabdar */ 16282654012fSReza Sabdar /*ARGSUSED*/ 16292654012fSReza Sabdar void 16302654012fSReza Sabdar ndmpd_audit_disconnect(ndmp_connection_t *conn) 16312654012fSReza Sabdar { 16322654012fSReza Sabdar adt_event_data_t *event; 16332654012fSReza Sabdar 16342654012fSReza Sabdar if ((event = adt_alloc_event(conn->conn_ah, 16352654012fSReza Sabdar ADT_ndmp_disconnect)) == NULL) { 16362654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Audit failure: %m."); 16372654012fSReza Sabdar return; 16382654012fSReza Sabdar } 16392654012fSReza Sabdar if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) 16402654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Audit failure: %m."); 16412654012fSReza Sabdar 16422654012fSReza Sabdar adt_free_event(event); 16432654012fSReza Sabdar } 16442654012fSReza Sabdar 16452654012fSReza Sabdar void * 16462654012fSReza Sabdar ndmp_malloc(size_t size) 16472654012fSReza Sabdar { 16482654012fSReza Sabdar void *data; 16492654012fSReza Sabdar 16502654012fSReza Sabdar if ((data = calloc(1, size)) == NULL) { 16512654012fSReza Sabdar NDMP_LOG(LOG_ERR, "Out of memory."); 16522654012fSReza Sabdar } 16532654012fSReza Sabdar 16542654012fSReza Sabdar return (data); 16552654012fSReza Sabdar } 1656