17917SReza.Sabdar@Sun.COM /* 2*8800SReza.Sabdar@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 37917SReza.Sabdar@Sun.COM * Use is subject to license terms. 47917SReza.Sabdar@Sun.COM */ 57917SReza.Sabdar@Sun.COM 67917SReza.Sabdar@Sun.COM /* 77917SReza.Sabdar@Sun.COM * BSD 3 Clause License 87917SReza.Sabdar@Sun.COM * 97917SReza.Sabdar@Sun.COM * Copyright (c) 2007, The Storage Networking Industry Association. 107917SReza.Sabdar@Sun.COM * 117917SReza.Sabdar@Sun.COM * Redistribution and use in source and binary forms, with or without 127917SReza.Sabdar@Sun.COM * modification, are permitted provided that the following conditions 137917SReza.Sabdar@Sun.COM * are met: 147917SReza.Sabdar@Sun.COM * - Redistributions of source code must retain the above copyright 157917SReza.Sabdar@Sun.COM * notice, this list of conditions and the following disclaimer. 167917SReza.Sabdar@Sun.COM * 177917SReza.Sabdar@Sun.COM * - Redistributions in binary form must reproduce the above copyright 187917SReza.Sabdar@Sun.COM * notice, this list of conditions and the following disclaimer in 197917SReza.Sabdar@Sun.COM * the documentation and/or other materials provided with the 207917SReza.Sabdar@Sun.COM * distribution. 217917SReza.Sabdar@Sun.COM * 227917SReza.Sabdar@Sun.COM * - Neither the name of The Storage Networking Industry Association (SNIA) 237917SReza.Sabdar@Sun.COM * nor the names of its contributors may be used to endorse or promote 247917SReza.Sabdar@Sun.COM * products derived from this software without specific prior written 257917SReza.Sabdar@Sun.COM * permission. 267917SReza.Sabdar@Sun.COM * 277917SReza.Sabdar@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 287917SReza.Sabdar@Sun.COM * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 297917SReza.Sabdar@Sun.COM * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 307917SReza.Sabdar@Sun.COM * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 317917SReza.Sabdar@Sun.COM * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 327917SReza.Sabdar@Sun.COM * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 337917SReza.Sabdar@Sun.COM * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 347917SReza.Sabdar@Sun.COM * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 357917SReza.Sabdar@Sun.COM * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 367917SReza.Sabdar@Sun.COM * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 377917SReza.Sabdar@Sun.COM * POSSIBILITY OF SUCH DAMAGE. 387917SReza.Sabdar@Sun.COM */ 397917SReza.Sabdar@Sun.COM /* Copyright (c) 2007, The Storage Networking Industry Association. */ 407917SReza.Sabdar@Sun.COM /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */ 417917SReza.Sabdar@Sun.COM 427917SReza.Sabdar@Sun.COM #include <sys/types.h> 437917SReza.Sabdar@Sun.COM #include <sys/socket.h> 447917SReza.Sabdar@Sun.COM #include <sys/time.h> 457917SReza.Sabdar@Sun.COM #include <sys/uio.h> 467917SReza.Sabdar@Sun.COM #include <unistd.h> 477917SReza.Sabdar@Sun.COM #include <string.h> 487917SReza.Sabdar@Sun.COM #include <stdlib.h> 497917SReza.Sabdar@Sun.COM #include <errno.h> 507917SReza.Sabdar@Sun.COM #include <netdb.h> 517917SReza.Sabdar@Sun.COM #include <netinet/in.h> 527917SReza.Sabdar@Sun.COM #include <arpa/inet.h> 537917SReza.Sabdar@Sun.COM #include "ndmpd.h" 547917SReza.Sabdar@Sun.COM #include "ndmpd_common.h" 557917SReza.Sabdar@Sun.COM 567917SReza.Sabdar@Sun.COM #define NDMP_PROC_ERR -1 577917SReza.Sabdar@Sun.COM #define NDMP_PROC_MSG 1 587917SReza.Sabdar@Sun.COM #define NDMP_PROC_REP 0 597917SReza.Sabdar@Sun.COM #define NDMP_PROC_REP_ERR 2 607917SReza.Sabdar@Sun.COM 617917SReza.Sabdar@Sun.COM /* 627917SReza.Sabdar@Sun.COM * The ndmp connection version can be set through command line. If command line 637917SReza.Sabdar@Sun.COM * is not specified it will be set from the ndmp SMF version property. 647917SReza.Sabdar@Sun.COM */ 657917SReza.Sabdar@Sun.COM int ndmp_ver = 0; 667917SReza.Sabdar@Sun.COM 677917SReza.Sabdar@Sun.COM /* 687917SReza.Sabdar@Sun.COM * The NDMP listening port number 697917SReza.Sabdar@Sun.COM */ 707917SReza.Sabdar@Sun.COM int ndmp_port = 0; 717917SReza.Sabdar@Sun.COM 727917SReza.Sabdar@Sun.COM /* 737917SReza.Sabdar@Sun.COM * Restore path mechanism definition 747917SReza.Sabdar@Sun.COM * 0 means partial path restore and 757917SReza.Sabdar@Sun.COM * 1 means full path restore. 767917SReza.Sabdar@Sun.COM * Refer to NDMP_FULL_RESTORE_PATH for partial path and full path definition. 777917SReza.Sabdar@Sun.COM */ 787917SReza.Sabdar@Sun.COM int ndmp_full_restore_path = 1; 797917SReza.Sabdar@Sun.COM 807917SReza.Sabdar@Sun.COM /* 817917SReza.Sabdar@Sun.COM * Do we support Direct Access Restore? 827917SReza.Sabdar@Sun.COM */ 837917SReza.Sabdar@Sun.COM int ndmp_dar_support = 0; 847917SReza.Sabdar@Sun.COM 857917SReza.Sabdar@Sun.COM /* 867917SReza.Sabdar@Sun.COM * ndmp_connection_t handler function 877917SReza.Sabdar@Sun.COM */ 887917SReza.Sabdar@Sun.COM static ndmpd_file_handler_func_t connection_file_handler; 897917SReza.Sabdar@Sun.COM 907917SReza.Sabdar@Sun.COM extern ndmp_handler_t ndmp_msghdl_tab[]; 917917SReza.Sabdar@Sun.COM 927917SReza.Sabdar@Sun.COM static int ndmp_readit(void *connection_handle, 937917SReza.Sabdar@Sun.COM caddr_t buf, 947917SReza.Sabdar@Sun.COM int len); 957917SReza.Sabdar@Sun.COM static int ndmp_writeit(void *connection_handle, 967917SReza.Sabdar@Sun.COM caddr_t buf, 977917SReza.Sabdar@Sun.COM int len); 987917SReza.Sabdar@Sun.COM static int ndmp_recv_msg(ndmp_connection_t *connection); 997917SReza.Sabdar@Sun.COM static int ndmp_process_messages(ndmp_connection_t *connection, 1007917SReza.Sabdar@Sun.COM boolean_t reply_expected); 1017917SReza.Sabdar@Sun.COM static ndmp_msg_handler_t *ndmp_get_handler(ndmp_connection_t *connection, 1027917SReza.Sabdar@Sun.COM ndmp_message message); 1037917SReza.Sabdar@Sun.COM static boolean_t ndmp_check_auth_required(ndmp_message message); 1047917SReza.Sabdar@Sun.COM static ndmp_handler_t *ndmp_get_interface(ndmp_message message); 1057917SReza.Sabdar@Sun.COM void *ndmpd_worker(void *ptarg); 1067917SReza.Sabdar@Sun.COM 1077917SReza.Sabdar@Sun.COM #ifdef lint 1087917SReza.Sabdar@Sun.COM bool_t 1097917SReza.Sabdar@Sun.COM xdr_ndmp_header(XDR *xdrs, ndmp_header *objp) 1107917SReza.Sabdar@Sun.COM { 1117917SReza.Sabdar@Sun.COM xdrs = xdrs; 1127917SReza.Sabdar@Sun.COM objp = objp; 1137917SReza.Sabdar@Sun.COM return (0); 1147917SReza.Sabdar@Sun.COM } 1157917SReza.Sabdar@Sun.COM #endif /* lint */ 1167917SReza.Sabdar@Sun.COM 1177917SReza.Sabdar@Sun.COM /* 1187917SReza.Sabdar@Sun.COM * ndmp_create_connection 1197917SReza.Sabdar@Sun.COM * 1207917SReza.Sabdar@Sun.COM * Allocate and initialize a connection structure. 1217917SReza.Sabdar@Sun.COM * 1227917SReza.Sabdar@Sun.COM * Parameters: 1237917SReza.Sabdar@Sun.COM * handler_tbl (input) - message handlers. 1247917SReza.Sabdar@Sun.COM * 1257917SReza.Sabdar@Sun.COM * Returns: 1267917SReza.Sabdar@Sun.COM * NULL - error 1277917SReza.Sabdar@Sun.COM * connection pointer 1287917SReza.Sabdar@Sun.COM * 1297917SReza.Sabdar@Sun.COM * Notes: 1307917SReza.Sabdar@Sun.COM * The returned connection should be destroyed using 1317917SReza.Sabdar@Sun.COM * ndmp_destroy_connection(). 1327917SReza.Sabdar@Sun.COM */ 1337917SReza.Sabdar@Sun.COM ndmp_connection_t * 1347917SReza.Sabdar@Sun.COM ndmp_create_connection(void) 1357917SReza.Sabdar@Sun.COM { 1367917SReza.Sabdar@Sun.COM ndmp_connection_t *connection; 1377917SReza.Sabdar@Sun.COM 1387917SReza.Sabdar@Sun.COM connection = ndmp_malloc(sizeof (ndmp_connection_t)); 1397917SReza.Sabdar@Sun.COM if (connection == NULL) 1407917SReza.Sabdar@Sun.COM return (NULL); 1417917SReza.Sabdar@Sun.COM 1427917SReza.Sabdar@Sun.COM connection->conn_sock = -1; 1437917SReza.Sabdar@Sun.COM connection->conn_my_sequence = 0; 1447917SReza.Sabdar@Sun.COM connection->conn_authorized = FALSE; 1457917SReza.Sabdar@Sun.COM connection->conn_eof = FALSE; 1467917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_body = 0; 1477917SReza.Sabdar@Sun.COM connection->conn_version = ndmp_ver; 1487917SReza.Sabdar@Sun.COM connection->conn_client_data = 0; 1497917SReza.Sabdar@Sun.COM (void) mutex_init(&connection->conn_lock, 0, NULL); 1507917SReza.Sabdar@Sun.COM connection->conn_xdrs.x_ops = 0; 1517917SReza.Sabdar@Sun.COM 1527917SReza.Sabdar@Sun.COM xdrrec_create(&connection->conn_xdrs, 0, 0, (caddr_t)connection, 1537917SReza.Sabdar@Sun.COM ndmp_readit, ndmp_writeit); 1547917SReza.Sabdar@Sun.COM 1557917SReza.Sabdar@Sun.COM if (connection->conn_xdrs.x_ops == 0) { 1567917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "xdrrec_create failed"); 1577917SReza.Sabdar@Sun.COM (void) mutex_destroy(&connection->conn_lock); 1587917SReza.Sabdar@Sun.COM (void) close(connection->conn_sock); 1597917SReza.Sabdar@Sun.COM free(connection); 1607917SReza.Sabdar@Sun.COM return (0); 1617917SReza.Sabdar@Sun.COM } 1627917SReza.Sabdar@Sun.COM return ((ndmp_connection_t *)connection); 1637917SReza.Sabdar@Sun.COM } 1647917SReza.Sabdar@Sun.COM 1657917SReza.Sabdar@Sun.COM /* 1667917SReza.Sabdar@Sun.COM * ndmp_destroy_connection 1677917SReza.Sabdar@Sun.COM * 1687917SReza.Sabdar@Sun.COM * Shutdown a connection and release allocated resources. 1697917SReza.Sabdar@Sun.COM * 1707917SReza.Sabdar@Sun.COM * Parameters: 1717917SReza.Sabdar@Sun.COM * connection_handle (Input) - connection handle. 1727917SReza.Sabdar@Sun.COM * 1737917SReza.Sabdar@Sun.COM * Returns: 1747917SReza.Sabdar@Sun.COM * void 1757917SReza.Sabdar@Sun.COM */ 1767917SReza.Sabdar@Sun.COM void 1777917SReza.Sabdar@Sun.COM ndmp_destroy_connection(ndmp_connection_t *connection_handle) 1787917SReza.Sabdar@Sun.COM { 1797917SReza.Sabdar@Sun.COM ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 1807917SReza.Sabdar@Sun.COM 1817917SReza.Sabdar@Sun.COM if (connection->conn_sock >= 0) { 1827917SReza.Sabdar@Sun.COM (void) mutex_destroy(&connection->conn_lock); 1837917SReza.Sabdar@Sun.COM (void) close(connection->conn_sock); 1847917SReza.Sabdar@Sun.COM connection->conn_sock = -1; 1857917SReza.Sabdar@Sun.COM } 1867917SReza.Sabdar@Sun.COM xdr_destroy(&connection->conn_xdrs); 1877917SReza.Sabdar@Sun.COM free(connection); 1887917SReza.Sabdar@Sun.COM } 1897917SReza.Sabdar@Sun.COM 1907917SReza.Sabdar@Sun.COM 1917917SReza.Sabdar@Sun.COM /* 1927917SReza.Sabdar@Sun.COM * ndmp_close 1937917SReza.Sabdar@Sun.COM * 1947917SReza.Sabdar@Sun.COM * Close a connection. 1957917SReza.Sabdar@Sun.COM * 1967917SReza.Sabdar@Sun.COM * Parameters: 1977917SReza.Sabdar@Sun.COM * connection_handle (Input) - connection handle. 1987917SReza.Sabdar@Sun.COM * 1997917SReza.Sabdar@Sun.COM * Returns: 2007917SReza.Sabdar@Sun.COM * void 2017917SReza.Sabdar@Sun.COM */ 2027917SReza.Sabdar@Sun.COM void 2037917SReza.Sabdar@Sun.COM ndmp_close(ndmp_connection_t *connection_handle) 2047917SReza.Sabdar@Sun.COM { 2057917SReza.Sabdar@Sun.COM ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 2067917SReza.Sabdar@Sun.COM 2077917SReza.Sabdar@Sun.COM ndmpd_audit_disconnect(connection); 2087917SReza.Sabdar@Sun.COM if (connection->conn_sock >= 0) { 2097917SReza.Sabdar@Sun.COM (void) mutex_destroy(&connection->conn_lock); 2107917SReza.Sabdar@Sun.COM (void) close(connection->conn_sock); 2117917SReza.Sabdar@Sun.COM connection->conn_sock = -1; 2127917SReza.Sabdar@Sun.COM } 2137917SReza.Sabdar@Sun.COM connection->conn_eof = TRUE; 2147917SReza.Sabdar@Sun.COM 2157917SReza.Sabdar@Sun.COM /* 2167917SReza.Sabdar@Sun.COM * We should close all the tapes that are used by this connection. 2177917SReza.Sabdar@Sun.COM * In some cases the ndmp client opens a tape, but does not close the 2187917SReza.Sabdar@Sun.COM * tape and closes the connection. 2197917SReza.Sabdar@Sun.COM */ 2207917SReza.Sabdar@Sun.COM ndmp_open_list_release(connection_handle); 2217917SReza.Sabdar@Sun.COM } 2227917SReza.Sabdar@Sun.COM 2237917SReza.Sabdar@Sun.COM /* 2247917SReza.Sabdar@Sun.COM * ndmp_start_worker 2257917SReza.Sabdar@Sun.COM * 2267917SReza.Sabdar@Sun.COM * Initializes and starts a ndmp_worker thread 2277917SReza.Sabdar@Sun.COM */ 2287917SReza.Sabdar@Sun.COM int 2297917SReza.Sabdar@Sun.COM ndmp_start_worker(ndmpd_worker_arg_t *argp) 2307917SReza.Sabdar@Sun.COM { 2317917SReza.Sabdar@Sun.COM pthread_attr_t tattr; 2327917SReza.Sabdar@Sun.COM int rc; 2337917SReza.Sabdar@Sun.COM 2347917SReza.Sabdar@Sun.COM (void) pthread_attr_init(&tattr); 2357917SReza.Sabdar@Sun.COM (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); 2367917SReza.Sabdar@Sun.COM rc = pthread_create(NULL, &tattr, ndmpd_worker, (void *)argp); 2377917SReza.Sabdar@Sun.COM (void) pthread_attr_destroy(&tattr); 2387917SReza.Sabdar@Sun.COM return (rc); 2397917SReza.Sabdar@Sun.COM } 2407917SReza.Sabdar@Sun.COM 2417917SReza.Sabdar@Sun.COM /* 2427917SReza.Sabdar@Sun.COM * ndmp_run 2437917SReza.Sabdar@Sun.COM * 2447917SReza.Sabdar@Sun.COM * Creates a socket for listening and accepting connections 2457917SReza.Sabdar@Sun.COM * from NDMP clients. 2467917SReza.Sabdar@Sun.COM * Accepts connections and passes each connection to the connection 2477917SReza.Sabdar@Sun.COM * handler. 2487917SReza.Sabdar@Sun.COM * 2497917SReza.Sabdar@Sun.COM * Parameters: 2507917SReza.Sabdar@Sun.COM * port (input) - NDMP server port. 2517917SReza.Sabdar@Sun.COM * If 0, the port number will be retrieved from 2527917SReza.Sabdar@Sun.COM * the network service database. If not found there, 2537917SReza.Sabdar@Sun.COM * the default NDMP port number (from ndmp.x) 2547917SReza.Sabdar@Sun.COM * will be used. 2557917SReza.Sabdar@Sun.COM * handler (input) - connection handler function. 2567917SReza.Sabdar@Sun.COM * 2577917SReza.Sabdar@Sun.COM * Returns: 2587917SReza.Sabdar@Sun.COM * This function normally never returns unless there's error. 2597917SReza.Sabdar@Sun.COM * -1 : error 2607917SReza.Sabdar@Sun.COM * 2617917SReza.Sabdar@Sun.COM * Notes: 2627917SReza.Sabdar@Sun.COM * This function does not return unless encountering an error 2637917SReza.Sabdar@Sun.COM * related to the listen socket. 2647917SReza.Sabdar@Sun.COM */ 2657917SReza.Sabdar@Sun.COM int 2667917SReza.Sabdar@Sun.COM ndmp_run(ulong_t port, ndmp_con_handler_func_t con_handler_func) 2677917SReza.Sabdar@Sun.COM { 2687917SReza.Sabdar@Sun.COM int ns; 2697917SReza.Sabdar@Sun.COM int on, tmp; 2707917SReza.Sabdar@Sun.COM int server_socket; 2717917SReza.Sabdar@Sun.COM unsigned int ipaddr; 2727917SReza.Sabdar@Sun.COM struct sockaddr_in sin; 2737917SReza.Sabdar@Sun.COM int flag = 1; 2747917SReza.Sabdar@Sun.COM ndmpd_worker_arg_t *argp; 2757917SReza.Sabdar@Sun.COM 2767917SReza.Sabdar@Sun.COM sin.sin_family = AF_INET; 2777917SReza.Sabdar@Sun.COM sin.sin_addr.s_addr = INADDR_ANY; 2787917SReza.Sabdar@Sun.COM sin.sin_port = htons(port); 2797917SReza.Sabdar@Sun.COM 2807917SReza.Sabdar@Sun.COM if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 2817917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Socket error: %m"); 2827917SReza.Sabdar@Sun.COM return (-1); 2837917SReza.Sabdar@Sun.COM } 2847917SReza.Sabdar@Sun.COM 2857917SReza.Sabdar@Sun.COM on = 1; 2867917SReza.Sabdar@Sun.COM (void) setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, 2877917SReza.Sabdar@Sun.COM (char *)&on, sizeof (on)); 2887917SReza.Sabdar@Sun.COM 2897917SReza.Sabdar@Sun.COM 2907917SReza.Sabdar@Sun.COM if (bind(server_socket, (struct sockaddr *)&sin, sizeof (sin)) < 0) { 2917917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "bind error: %m"); 2927917SReza.Sabdar@Sun.COM (void) close(server_socket); 2937917SReza.Sabdar@Sun.COM return (-1); 2947917SReza.Sabdar@Sun.COM } 2957917SReza.Sabdar@Sun.COM if (listen(server_socket, 5) < 0) { 2967917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "listen error: %m"); 2977917SReza.Sabdar@Sun.COM (void) close(server_socket); 2987917SReza.Sabdar@Sun.COM return (-1); 2997917SReza.Sabdar@Sun.COM } 3007917SReza.Sabdar@Sun.COM 3017917SReza.Sabdar@Sun.COM for (; ; ) { 3027917SReza.Sabdar@Sun.COM if ((ns = tcp_accept(server_socket, &ipaddr)) < 0) { 3037917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "tcp_accept error: %m"); 3047917SReza.Sabdar@Sun.COM continue; 3057917SReza.Sabdar@Sun.COM } 3067917SReza.Sabdar@Sun.COM 3077917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "connection fd: %d", ns); 3087917SReza.Sabdar@Sun.COM 3097917SReza.Sabdar@Sun.COM /* 3107917SReza.Sabdar@Sun.COM * 'css' and 'crs' in the following env variables stand for: 3117917SReza.Sabdar@Sun.COM * 'connection send size' and 'connection receive size'. 3127917SReza.Sabdar@Sun.COM */ 3137917SReza.Sabdar@Sun.COM tmp = atoi((const char *)ndmpd_get_prop_default(NDMP_SOCKET_CSS, 3147917SReza.Sabdar@Sun.COM "65")); 3157917SReza.Sabdar@Sun.COM if (tmp <= 0) 3167917SReza.Sabdar@Sun.COM tmp = 65; 3177917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "css: %d_KB", tmp); 3187917SReza.Sabdar@Sun.COM ndmp_set_socket_snd_buf(ns, tmp * KILOBYTE); 3197917SReza.Sabdar@Sun.COM 3207917SReza.Sabdar@Sun.COM tmp = atoi((const char *)ndmpd_get_prop_default(NDMP_SOCKET_CRS, 3217917SReza.Sabdar@Sun.COM "80")); 3227917SReza.Sabdar@Sun.COM if (tmp <= 0) 3237917SReza.Sabdar@Sun.COM tmp = 80; 3247917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "crs: %d_KB", tmp); 3257917SReza.Sabdar@Sun.COM ndmp_set_socket_rcv_buf(ns, tmp * KILOBYTE); 3267917SReza.Sabdar@Sun.COM 3277917SReza.Sabdar@Sun.COM ndmp_set_socket_nodelay(ns); 3287917SReza.Sabdar@Sun.COM (void) setsockopt(ns, SOL_SOCKET, SO_KEEPALIVE, &flag, 3297917SReza.Sabdar@Sun.COM sizeof (flag)); 3307917SReza.Sabdar@Sun.COM 3317917SReza.Sabdar@Sun.COM if ((argp = ndmp_malloc(sizeof (ndmpd_worker_arg_t))) != NULL) { 3327917SReza.Sabdar@Sun.COM argp->nw_sock = ns; 3337917SReza.Sabdar@Sun.COM argp->nw_ipaddr = ipaddr; 3347917SReza.Sabdar@Sun.COM argp->nw_con_handler_func = con_handler_func; 3357917SReza.Sabdar@Sun.COM (void) ndmp_start_worker(argp); 3367917SReza.Sabdar@Sun.COM } 3377917SReza.Sabdar@Sun.COM } 3387917SReza.Sabdar@Sun.COM } 3397917SReza.Sabdar@Sun.COM 3407917SReza.Sabdar@Sun.COM /* 3417917SReza.Sabdar@Sun.COM * ndmpd_worker thread 3427917SReza.Sabdar@Sun.COM * 3437917SReza.Sabdar@Sun.COM * Parameters: 3447917SReza.Sabdar@Sun.COM * argp (input) - structure containing socket and handler function 3457917SReza.Sabdar@Sun.COM * 3467917SReza.Sabdar@Sun.COM * Returns: 3477917SReza.Sabdar@Sun.COM * 0 - successful connection. 3487917SReza.Sabdar@Sun.COM * -1 - error. 3497917SReza.Sabdar@Sun.COM */ 3507917SReza.Sabdar@Sun.COM void * 3517917SReza.Sabdar@Sun.COM ndmpd_worker(void *ptarg) 3527917SReza.Sabdar@Sun.COM { 3537917SReza.Sabdar@Sun.COM int sock; 3547917SReza.Sabdar@Sun.COM ndmp_connection_t *connection; 3557917SReza.Sabdar@Sun.COM ndmpd_worker_arg_t *argp = (ndmpd_worker_arg_t *)ptarg; 3567917SReza.Sabdar@Sun.COM 3577917SReza.Sabdar@Sun.COM if (!argp) 3587917SReza.Sabdar@Sun.COM return ((void *)-1); 3597917SReza.Sabdar@Sun.COM 3607917SReza.Sabdar@Sun.COM NS_INC(trun); 3617917SReza.Sabdar@Sun.COM sock = argp->nw_sock; 3627917SReza.Sabdar@Sun.COM 3637917SReza.Sabdar@Sun.COM if ((connection = ndmp_create_connection()) == NULL) { 3647917SReza.Sabdar@Sun.COM (void) close(sock); 3657917SReza.Sabdar@Sun.COM free(argp); 3667917SReza.Sabdar@Sun.COM exit(1); 3677917SReza.Sabdar@Sun.COM } 3687917SReza.Sabdar@Sun.COM 3697917SReza.Sabdar@Sun.COM /* initialize auditing session */ 3707917SReza.Sabdar@Sun.COM if (adt_start_session(&connection->conn_ah, NULL, 0) != 0) { 3717917SReza.Sabdar@Sun.COM free(argp); 3727917SReza.Sabdar@Sun.COM return ((void *)-1); 3737917SReza.Sabdar@Sun.COM } 3747917SReza.Sabdar@Sun.COM 3757917SReza.Sabdar@Sun.COM ((ndmp_connection_t *)connection)->conn_sock = sock; 3767917SReza.Sabdar@Sun.COM (*argp->nw_con_handler_func)(connection); 3777917SReza.Sabdar@Sun.COM (void) adt_end_session(connection->conn_ah); 3787917SReza.Sabdar@Sun.COM ndmp_destroy_connection(connection); 3797917SReza.Sabdar@Sun.COM NS_DEC(trun); 3807917SReza.Sabdar@Sun.COM 3817917SReza.Sabdar@Sun.COM free(argp); 3827917SReza.Sabdar@Sun.COM return (NULL); 3837917SReza.Sabdar@Sun.COM } 3847917SReza.Sabdar@Sun.COM 3857917SReza.Sabdar@Sun.COM /* 3867917SReza.Sabdar@Sun.COM * ndmp_process_requests 3877917SReza.Sabdar@Sun.COM * 3887917SReza.Sabdar@Sun.COM * Reads the next request message into the stream buffer. 3897917SReza.Sabdar@Sun.COM * Processes messages until the stream buffer is empty. 3907917SReza.Sabdar@Sun.COM * 3917917SReza.Sabdar@Sun.COM * Parameters: 3927917SReza.Sabdar@Sun.COM * connection_handle (input) - connection handle. 3937917SReza.Sabdar@Sun.COM * 3947917SReza.Sabdar@Sun.COM * Returns: 3957917SReza.Sabdar@Sun.COM * 0 - 1 or more messages successfully processed. 3967917SReza.Sabdar@Sun.COM * -1 - error; connection no longer established. 3977917SReza.Sabdar@Sun.COM */ 3987917SReza.Sabdar@Sun.COM int 3997917SReza.Sabdar@Sun.COM ndmp_process_requests(ndmp_connection_t *connection_handle) 4007917SReza.Sabdar@Sun.COM { 4017917SReza.Sabdar@Sun.COM int rv; 4027917SReza.Sabdar@Sun.COM ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 4037917SReza.Sabdar@Sun.COM 4047917SReza.Sabdar@Sun.COM (void) mutex_lock(&connection->conn_lock); 4057917SReza.Sabdar@Sun.COM rv = 0; 4067917SReza.Sabdar@Sun.COM if (ndmp_process_messages(connection, FALSE) < 0) 4077917SReza.Sabdar@Sun.COM rv = -1; 4087917SReza.Sabdar@Sun.COM 4097917SReza.Sabdar@Sun.COM (void) mutex_unlock(&connection->conn_lock); 4107917SReza.Sabdar@Sun.COM return (rv); 4117917SReza.Sabdar@Sun.COM } 4127917SReza.Sabdar@Sun.COM 4137917SReza.Sabdar@Sun.COM 4147917SReza.Sabdar@Sun.COM /* 4157917SReza.Sabdar@Sun.COM * ndmp_send_request 4167917SReza.Sabdar@Sun.COM * 4177917SReza.Sabdar@Sun.COM * Send an NDMP request message. 4187917SReza.Sabdar@Sun.COM * 4197917SReza.Sabdar@Sun.COM * Parameters: 4207917SReza.Sabdar@Sun.COM * connection_handle (input) - connection pointer. 4217917SReza.Sabdar@Sun.COM * message (input) - message number. 4227917SReza.Sabdar@Sun.COM * err (input) - error code to place in header. 4237917SReza.Sabdar@Sun.COM * request_data (input) - message body. 4247917SReza.Sabdar@Sun.COM * reply (output) - reply message. If 0, reply will be 4257917SReza.Sabdar@Sun.COM * discarded. 4267917SReza.Sabdar@Sun.COM * 4277917SReza.Sabdar@Sun.COM * Returns: 4287917SReza.Sabdar@Sun.COM * 0 - successful send. 4297917SReza.Sabdar@Sun.COM * -1 - error. 4307917SReza.Sabdar@Sun.COM * otherwise - error from reply header. 4317917SReza.Sabdar@Sun.COM * 4327917SReza.Sabdar@Sun.COM * Notes: 4337917SReza.Sabdar@Sun.COM * - The reply body is only returned if the error code is NDMP_NO_ERR. 4347917SReza.Sabdar@Sun.COM */ 4357917SReza.Sabdar@Sun.COM int 4367917SReza.Sabdar@Sun.COM ndmp_send_request(ndmp_connection_t *connection_handle, ndmp_message message, 4377917SReza.Sabdar@Sun.COM ndmp_error err, void *request_data, void **reply) 4387917SReza.Sabdar@Sun.COM { 4397917SReza.Sabdar@Sun.COM ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 4407917SReza.Sabdar@Sun.COM ndmp_header header; 4417917SReza.Sabdar@Sun.COM ndmp_msg_handler_t *handler; 4427917SReza.Sabdar@Sun.COM int r; 4437917SReza.Sabdar@Sun.COM struct timeval time; 4447917SReza.Sabdar@Sun.COM 4457917SReza.Sabdar@Sun.COM /* Lookup info necessary for processing this request. */ 4467917SReza.Sabdar@Sun.COM if (!(handler = ndmp_get_handler(connection, message))) { 4477917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Sending message 0x%x: not supported", 4487917SReza.Sabdar@Sun.COM message); 4497917SReza.Sabdar@Sun.COM return (-1); 4507917SReza.Sabdar@Sun.COM } 4517917SReza.Sabdar@Sun.COM (void) gettimeofday(&time, 0); 4527917SReza.Sabdar@Sun.COM 4537917SReza.Sabdar@Sun.COM header.sequence = ++(connection->conn_my_sequence); 4547917SReza.Sabdar@Sun.COM header.time_stamp = time.tv_sec; 4557917SReza.Sabdar@Sun.COM header.message_type = NDMP_MESSAGE_REQUEST; 4567917SReza.Sabdar@Sun.COM header.message = message; 4577917SReza.Sabdar@Sun.COM header.reply_sequence = 0; 4587917SReza.Sabdar@Sun.COM header.error = err; 4597917SReza.Sabdar@Sun.COM 4607917SReza.Sabdar@Sun.COM connection->conn_xdrs.x_op = XDR_ENCODE; 4617917SReza.Sabdar@Sun.COM if (!xdr_ndmp_header(&connection->conn_xdrs, &header)) { 4627917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 4637917SReza.Sabdar@Sun.COM "Sending message 0x%x: encoding request header", message); 4647917SReza.Sabdar@Sun.COM (void) xdrrec_endofrecord(&connection->conn_xdrs, 1); 4657917SReza.Sabdar@Sun.COM return (-1); 4667917SReza.Sabdar@Sun.COM } 4677917SReza.Sabdar@Sun.COM if (err == NDMP_NO_ERR && handler->mh_xdr_request && request_data) { 4687917SReza.Sabdar@Sun.COM if (!(*handler->mh_xdr_request)(&connection->conn_xdrs, 4697917SReza.Sabdar@Sun.COM request_data)) { 4707917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 4717917SReza.Sabdar@Sun.COM "Sending message 0x%x: encoding request body", 4727917SReza.Sabdar@Sun.COM message); 4737917SReza.Sabdar@Sun.COM (void) xdrrec_endofrecord(&connection->conn_xdrs, 1); 4747917SReza.Sabdar@Sun.COM return (-1); 4757917SReza.Sabdar@Sun.COM } 4767917SReza.Sabdar@Sun.COM } 4777917SReza.Sabdar@Sun.COM (void) xdrrec_endofrecord(&connection->conn_xdrs, 1); 4787917SReza.Sabdar@Sun.COM 4797917SReza.Sabdar@Sun.COM if (handler->mh_xdr_reply == 0) { 4807917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "handler->mh_xdr_reply == 0"); 4817917SReza.Sabdar@Sun.COM return (0); 4827917SReza.Sabdar@Sun.COM } 4837917SReza.Sabdar@Sun.COM 4847917SReza.Sabdar@Sun.COM /* 4857917SReza.Sabdar@Sun.COM * Process messages until the reply to this request has been 4867917SReza.Sabdar@Sun.COM * processed. 4877917SReza.Sabdar@Sun.COM */ 4887917SReza.Sabdar@Sun.COM for (; ; ) { 4897917SReza.Sabdar@Sun.COM r = ndmp_process_messages(connection, TRUE); 4907917SReza.Sabdar@Sun.COM 4917917SReza.Sabdar@Sun.COM /* connection error? */ 4927917SReza.Sabdar@Sun.COM if (r < 0) 4937917SReza.Sabdar@Sun.COM return (-1); 4947917SReza.Sabdar@Sun.COM 4957917SReza.Sabdar@Sun.COM /* no reply received? */ 4967917SReza.Sabdar@Sun.COM if (r == 0) 4977917SReza.Sabdar@Sun.COM continue; 4987917SReza.Sabdar@Sun.COM 4997917SReza.Sabdar@Sun.COM /* reply received? */ 5007917SReza.Sabdar@Sun.COM if (r == 1) { 5017917SReza.Sabdar@Sun.COM if (message != 5027917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_hdr.message) { 5037917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 5047917SReza.Sabdar@Sun.COM "Received unexpected reply 0x%x", 5057917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_hdr.message); 5067917SReza.Sabdar@Sun.COM ndmp_free_message(connection_handle); 5077917SReza.Sabdar@Sun.COM return (-1); 5087917SReza.Sabdar@Sun.COM } 5097917SReza.Sabdar@Sun.COM if (reply != NULL) 5107917SReza.Sabdar@Sun.COM *reply = connection->conn_msginfo.mi_body; 5117917SReza.Sabdar@Sun.COM else 5127917SReza.Sabdar@Sun.COM ndmp_free_message(connection_handle); 5137917SReza.Sabdar@Sun.COM 5147917SReza.Sabdar@Sun.COM return (connection->conn_msginfo.mi_hdr.error); 5157917SReza.Sabdar@Sun.COM } 5167917SReza.Sabdar@Sun.COM /* error handling reply */ 5177917SReza.Sabdar@Sun.COM 5187917SReza.Sabdar@Sun.COM return (-1); 5197917SReza.Sabdar@Sun.COM } 5207917SReza.Sabdar@Sun.COM } 5217917SReza.Sabdar@Sun.COM 5227917SReza.Sabdar@Sun.COM 5237917SReza.Sabdar@Sun.COM /* 5247917SReza.Sabdar@Sun.COM * ndmp_send_request_lock 5257917SReza.Sabdar@Sun.COM * 5267917SReza.Sabdar@Sun.COM * A wrapper for ndmp_send_request with locks. 5277917SReza.Sabdar@Sun.COM * 5287917SReza.Sabdar@Sun.COM * Parameters: 5297917SReza.Sabdar@Sun.COM * connection_handle (input) - connection pointer. 5307917SReza.Sabdar@Sun.COM * message (input) - message number. 5317917SReza.Sabdar@Sun.COM * err (input) - error code to place in header. 5327917SReza.Sabdar@Sun.COM * request_data (input) - message body. 5337917SReza.Sabdar@Sun.COM * reply (output) - reply message. If 0, reply will be 5347917SReza.Sabdar@Sun.COM * discarded. 5357917SReza.Sabdar@Sun.COM * 5367917SReza.Sabdar@Sun.COM * Returns: 5377917SReza.Sabdar@Sun.COM * 0 - successful send. 5387917SReza.Sabdar@Sun.COM * -1 - error. 5397917SReza.Sabdar@Sun.COM * otherwise - error from reply header. 5407917SReza.Sabdar@Sun.COM * 5417917SReza.Sabdar@Sun.COM * Notes: 5427917SReza.Sabdar@Sun.COM * - The reply body is only returned if the error code is NDMP_NO_ERR. 5437917SReza.Sabdar@Sun.COM */ 5447917SReza.Sabdar@Sun.COM int 5457917SReza.Sabdar@Sun.COM ndmp_send_request_lock(ndmp_connection_t *connection_handle, 5467917SReza.Sabdar@Sun.COM ndmp_message message, ndmp_error err, void *request_data, void **reply) 5477917SReza.Sabdar@Sun.COM { 5487917SReza.Sabdar@Sun.COM int rv; 5497917SReza.Sabdar@Sun.COM ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 5507917SReza.Sabdar@Sun.COM 5517917SReza.Sabdar@Sun.COM (void) mutex_lock(&connection->conn_lock); 5527917SReza.Sabdar@Sun.COM 5537917SReza.Sabdar@Sun.COM rv = ndmp_send_request(connection_handle, message, err, request_data, 5547917SReza.Sabdar@Sun.COM reply); 5557917SReza.Sabdar@Sun.COM (void) mutex_unlock(&connection->conn_lock); 5567917SReza.Sabdar@Sun.COM return (rv); 5577917SReza.Sabdar@Sun.COM } 5587917SReza.Sabdar@Sun.COM 5597917SReza.Sabdar@Sun.COM 5607917SReza.Sabdar@Sun.COM /* 5617917SReza.Sabdar@Sun.COM * ndmp_send_response 5627917SReza.Sabdar@Sun.COM * 5637917SReza.Sabdar@Sun.COM * Send an NDMP reply message. 5647917SReza.Sabdar@Sun.COM * 5657917SReza.Sabdar@Sun.COM * Parameters: 5667917SReza.Sabdar@Sun.COM * connection_handle (input) - connection pointer. 5677917SReza.Sabdar@Sun.COM * err (input) - error code to place in header. 5687917SReza.Sabdar@Sun.COM * reply (input) - reply message body. 5697917SReza.Sabdar@Sun.COM * 5707917SReza.Sabdar@Sun.COM * Returns: 5717917SReza.Sabdar@Sun.COM * 0 - successful send. 5727917SReza.Sabdar@Sun.COM * -1 - error. 5737917SReza.Sabdar@Sun.COM * 5747917SReza.Sabdar@Sun.COM * Notes: 5757917SReza.Sabdar@Sun.COM * - The body is only sent if the error code is NDMP_NO_ERR. 5767917SReza.Sabdar@Sun.COM */ 5777917SReza.Sabdar@Sun.COM int 5787917SReza.Sabdar@Sun.COM ndmp_send_response(ndmp_connection_t *connection_handle, ndmp_error err, 5797917SReza.Sabdar@Sun.COM void *reply) 5807917SReza.Sabdar@Sun.COM { 5817917SReza.Sabdar@Sun.COM ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 5827917SReza.Sabdar@Sun.COM ndmp_header header; 5837917SReza.Sabdar@Sun.COM struct timeval time; 5847917SReza.Sabdar@Sun.COM 5857917SReza.Sabdar@Sun.COM (void) gettimeofday(&time, 0); 5867917SReza.Sabdar@Sun.COM 5877917SReza.Sabdar@Sun.COM header.sequence = ++(connection->conn_my_sequence); 5887917SReza.Sabdar@Sun.COM header.time_stamp = time.tv_sec; 5897917SReza.Sabdar@Sun.COM header.message_type = NDMP_MESSAGE_REPLY; 5907917SReza.Sabdar@Sun.COM header.message = connection->conn_msginfo.mi_hdr.message; 5917917SReza.Sabdar@Sun.COM header.reply_sequence = connection->conn_msginfo.mi_hdr.sequence; 5927917SReza.Sabdar@Sun.COM header.error = err; 5937917SReza.Sabdar@Sun.COM 5947917SReza.Sabdar@Sun.COM connection->conn_xdrs.x_op = XDR_ENCODE; 5957917SReza.Sabdar@Sun.COM if (!xdr_ndmp_header(&connection->conn_xdrs, &header)) { 5967917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Sending message 0x%x: " 5977917SReza.Sabdar@Sun.COM "encoding reply header", 5987917SReza.Sabdar@Sun.COM header.message); 5997917SReza.Sabdar@Sun.COM (void) xdrrec_endofrecord(&connection->conn_xdrs, 1); 6007917SReza.Sabdar@Sun.COM return (-1); 6017917SReza.Sabdar@Sun.COM } 6027917SReza.Sabdar@Sun.COM if (err == NDMP_NO_ERR && 6037917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_handler->mh_xdr_reply && 6047917SReza.Sabdar@Sun.COM reply) { 6057917SReza.Sabdar@Sun.COM if (!(*connection->conn_msginfo.mi_handler->mh_xdr_reply)( 6067917SReza.Sabdar@Sun.COM &connection->conn_xdrs, reply)) { 6077917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 6087917SReza.Sabdar@Sun.COM "Sending message 0x%x: encoding reply body", 6097917SReza.Sabdar@Sun.COM header.message); 6107917SReza.Sabdar@Sun.COM (void) xdrrec_endofrecord(&connection->conn_xdrs, 1); 6117917SReza.Sabdar@Sun.COM return (-1); 6127917SReza.Sabdar@Sun.COM } 6137917SReza.Sabdar@Sun.COM } 6147917SReza.Sabdar@Sun.COM (void) xdrrec_endofrecord(&connection->conn_xdrs, 1); 6157917SReza.Sabdar@Sun.COM return (0); 6167917SReza.Sabdar@Sun.COM } 6177917SReza.Sabdar@Sun.COM 6187917SReza.Sabdar@Sun.COM /* 6197917SReza.Sabdar@Sun.COM * ndmp_free_message 6207917SReza.Sabdar@Sun.COM * 6217917SReza.Sabdar@Sun.COM * Free the memory of NDMP message body. 6227917SReza.Sabdar@Sun.COM * 6237917SReza.Sabdar@Sun.COM * Parameters: 6247917SReza.Sabdar@Sun.COM * connection_handle (input) - connection pointer. 6257917SReza.Sabdar@Sun.COM * 6267917SReza.Sabdar@Sun.COM * Returns: 6277917SReza.Sabdar@Sun.COM * void 6287917SReza.Sabdar@Sun.COM * 6297917SReza.Sabdar@Sun.COM */ 6307917SReza.Sabdar@Sun.COM void 6317917SReza.Sabdar@Sun.COM ndmp_free_message(ndmp_connection_t *connection_handle) 6327917SReza.Sabdar@Sun.COM { 6337917SReza.Sabdar@Sun.COM ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 6347917SReza.Sabdar@Sun.COM 6357917SReza.Sabdar@Sun.COM if (connection->conn_msginfo.mi_handler == NULL || 6367917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_body == NULL) 6377917SReza.Sabdar@Sun.COM return; 6387917SReza.Sabdar@Sun.COM 6397917SReza.Sabdar@Sun.COM connection->conn_xdrs.x_op = XDR_FREE; 6407917SReza.Sabdar@Sun.COM if (connection->conn_msginfo.mi_hdr.message_type == 6417917SReza.Sabdar@Sun.COM NDMP_MESSAGE_REQUEST) { 6427917SReza.Sabdar@Sun.COM if (connection->conn_msginfo.mi_handler->mh_xdr_request) 6437917SReza.Sabdar@Sun.COM (*connection->conn_msginfo.mi_handler->mh_xdr_request)( 6447917SReza.Sabdar@Sun.COM &connection->conn_xdrs, 6457917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_body); 6467917SReza.Sabdar@Sun.COM } else { 6477917SReza.Sabdar@Sun.COM if (connection->conn_msginfo.mi_handler->mh_xdr_reply) 6487917SReza.Sabdar@Sun.COM (*connection->conn_msginfo.mi_handler->mh_xdr_reply)( 6497917SReza.Sabdar@Sun.COM &connection->conn_xdrs, 6507917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_body); 6517917SReza.Sabdar@Sun.COM } 6527917SReza.Sabdar@Sun.COM 6537917SReza.Sabdar@Sun.COM (void) free(connection->conn_msginfo.mi_body); 6547917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_body = 0; 6557917SReza.Sabdar@Sun.COM } 6567917SReza.Sabdar@Sun.COM 6577917SReza.Sabdar@Sun.COM /* 6587917SReza.Sabdar@Sun.COM * ndmp_get_fd 6597917SReza.Sabdar@Sun.COM * 6607917SReza.Sabdar@Sun.COM * Returns the connection file descriptor. 6617917SReza.Sabdar@Sun.COM * 6627917SReza.Sabdar@Sun.COM * Parameters: 6637917SReza.Sabdar@Sun.COM * connection_handle (input) - connection handle 6647917SReza.Sabdar@Sun.COM * 6657917SReza.Sabdar@Sun.COM * Returns: 6667917SReza.Sabdar@Sun.COM * >=0 - file descriptor. 6677917SReza.Sabdar@Sun.COM * -1 - connection not open. 6687917SReza.Sabdar@Sun.COM */ 6697917SReza.Sabdar@Sun.COM int 6707917SReza.Sabdar@Sun.COM ndmp_get_fd(ndmp_connection_t *connection_handle) 6717917SReza.Sabdar@Sun.COM { 6727917SReza.Sabdar@Sun.COM return (((ndmp_connection_t *)connection_handle)->conn_sock); 6737917SReza.Sabdar@Sun.COM } 6747917SReza.Sabdar@Sun.COM 6757917SReza.Sabdar@Sun.COM 6767917SReza.Sabdar@Sun.COM /* 6777917SReza.Sabdar@Sun.COM * ndmp_set_client_data 6787917SReza.Sabdar@Sun.COM * 6797917SReza.Sabdar@Sun.COM * This function provides a means for the library client to provide 6807917SReza.Sabdar@Sun.COM * a pointer to some user data structure that is retrievable by 6817917SReza.Sabdar@Sun.COM * each message handler via ndmp_get_client_data. 6827917SReza.Sabdar@Sun.COM * 6837917SReza.Sabdar@Sun.COM * Parameters: 6847917SReza.Sabdar@Sun.COM * connection_handle (input) - connection handle. 6857917SReza.Sabdar@Sun.COM * client_data (input) - user data pointer. 6867917SReza.Sabdar@Sun.COM * 6877917SReza.Sabdar@Sun.COM * Returns: 6887917SReza.Sabdar@Sun.COM * void 6897917SReza.Sabdar@Sun.COM */ 6907917SReza.Sabdar@Sun.COM void 6917917SReza.Sabdar@Sun.COM ndmp_set_client_data(ndmp_connection_t *connection_handle, void *client_data) 6927917SReza.Sabdar@Sun.COM { 6937917SReza.Sabdar@Sun.COM ((ndmp_connection_t *)connection_handle)->conn_client_data = 6947917SReza.Sabdar@Sun.COM client_data; 6957917SReza.Sabdar@Sun.COM } 6967917SReza.Sabdar@Sun.COM 6977917SReza.Sabdar@Sun.COM 6987917SReza.Sabdar@Sun.COM /* 6997917SReza.Sabdar@Sun.COM * ndmp_get_client_data 7007917SReza.Sabdar@Sun.COM * 7017917SReza.Sabdar@Sun.COM * This function provides a means for the library client to provide 7027917SReza.Sabdar@Sun.COM * a pointer to some user data structure that is retrievable by 7037917SReza.Sabdar@Sun.COM * each message handler via ndmp_get_client_data. 7047917SReza.Sabdar@Sun.COM * 7057917SReza.Sabdar@Sun.COM * Parameters: 7067917SReza.Sabdar@Sun.COM * connection_handle (input) - connection handle. 7077917SReza.Sabdar@Sun.COM * 7087917SReza.Sabdar@Sun.COM * Returns: 7097917SReza.Sabdar@Sun.COM * client data pointer. 7107917SReza.Sabdar@Sun.COM */ 7117917SReza.Sabdar@Sun.COM void * 7127917SReza.Sabdar@Sun.COM ndmp_get_client_data(ndmp_connection_t *connection_handle) 7137917SReza.Sabdar@Sun.COM { 7147917SReza.Sabdar@Sun.COM return (((ndmp_connection_t *)connection_handle)->conn_client_data); 7157917SReza.Sabdar@Sun.COM } 7167917SReza.Sabdar@Sun.COM 7177917SReza.Sabdar@Sun.COM 7187917SReza.Sabdar@Sun.COM /* 7197917SReza.Sabdar@Sun.COM * ndmp_set_version 7207917SReza.Sabdar@Sun.COM * 7217917SReza.Sabdar@Sun.COM * Sets the NDMP protocol version to be used on the connection. 7227917SReza.Sabdar@Sun.COM * 7237917SReza.Sabdar@Sun.COM * Parameters: 7247917SReza.Sabdar@Sun.COM * connection_handle (input) - connection handle. 7257917SReza.Sabdar@Sun.COM * version (input) - protocol version. 7267917SReza.Sabdar@Sun.COM * 7277917SReza.Sabdar@Sun.COM * Returns: 7287917SReza.Sabdar@Sun.COM * void 7297917SReza.Sabdar@Sun.COM */ 7307917SReza.Sabdar@Sun.COM void 7317917SReza.Sabdar@Sun.COM ndmp_set_version(ndmp_connection_t *connection_handle, ushort_t version) 7327917SReza.Sabdar@Sun.COM { 7337917SReza.Sabdar@Sun.COM ((ndmp_connection_t *)connection_handle)->conn_version = version; 7347917SReza.Sabdar@Sun.COM } 7357917SReza.Sabdar@Sun.COM 7367917SReza.Sabdar@Sun.COM 7377917SReza.Sabdar@Sun.COM /* 7387917SReza.Sabdar@Sun.COM * ndmp_get_version 7397917SReza.Sabdar@Sun.COM * 7407917SReza.Sabdar@Sun.COM * Gets the NDMP protocol version in use on the connection. 7417917SReza.Sabdar@Sun.COM * 7427917SReza.Sabdar@Sun.COM * Parameters: 7437917SReza.Sabdar@Sun.COM * connection_handle (input) - connection handle. 7447917SReza.Sabdar@Sun.COM * version (input) - protocol version. 7457917SReza.Sabdar@Sun.COM * 7467917SReza.Sabdar@Sun.COM * Returns: 7477917SReza.Sabdar@Sun.COM * void 7487917SReza.Sabdar@Sun.COM */ 7497917SReza.Sabdar@Sun.COM ushort_t 7507917SReza.Sabdar@Sun.COM ndmp_get_version(ndmp_connection_t *connection_handle) 7517917SReza.Sabdar@Sun.COM { 7527917SReza.Sabdar@Sun.COM return (((ndmp_connection_t *)connection_handle)->conn_version); 7537917SReza.Sabdar@Sun.COM } 7547917SReza.Sabdar@Sun.COM 7557917SReza.Sabdar@Sun.COM 7567917SReza.Sabdar@Sun.COM /* 7577917SReza.Sabdar@Sun.COM * ndmp_set_authorized 7587917SReza.Sabdar@Sun.COM * 7597917SReza.Sabdar@Sun.COM * Mark the connection as either having been authorized or not. 7607917SReza.Sabdar@Sun.COM * 7617917SReza.Sabdar@Sun.COM * Parameters: 7627917SReza.Sabdar@Sun.COM * connection_handle (input) - connection handle. 7637917SReza.Sabdar@Sun.COM * authorized (input) - TRUE or FALSE. 7647917SReza.Sabdar@Sun.COM * 7657917SReza.Sabdar@Sun.COM * Returns: 7667917SReza.Sabdar@Sun.COM * void 7677917SReza.Sabdar@Sun.COM */ 7687917SReza.Sabdar@Sun.COM void 7697917SReza.Sabdar@Sun.COM ndmp_set_authorized(ndmp_connection_t *connection_handle, boolean_t authorized) 7707917SReza.Sabdar@Sun.COM { 7717917SReza.Sabdar@Sun.COM ((ndmp_connection_t *)connection_handle)->conn_authorized = authorized; 7727917SReza.Sabdar@Sun.COM } 7737917SReza.Sabdar@Sun.COM 7747917SReza.Sabdar@Sun.COM 7757917SReza.Sabdar@Sun.COM /* 7767917SReza.Sabdar@Sun.COM * ndmpd_main 7777917SReza.Sabdar@Sun.COM * 7787917SReza.Sabdar@Sun.COM * NDMP main function called from main(). 7797917SReza.Sabdar@Sun.COM * 7807917SReza.Sabdar@Sun.COM * Parameters: 7817917SReza.Sabdar@Sun.COM * void 7827917SReza.Sabdar@Sun.COM * 7837917SReza.Sabdar@Sun.COM * Returns: 7847917SReza.Sabdar@Sun.COM * void 7857917SReza.Sabdar@Sun.COM */ 7867917SReza.Sabdar@Sun.COM void 7877917SReza.Sabdar@Sun.COM ndmpd_main(void) 7887917SReza.Sabdar@Sun.COM { 7897917SReza.Sabdar@Sun.COM char *propval; 7907917SReza.Sabdar@Sun.COM 7917917SReza.Sabdar@Sun.COM ndmp_load_params(); 792*8800SReza.Sabdar@Sun.COM if (ndmp_log_open_file() != 0) { 793*8800SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, 794*8800SReza.Sabdar@Sun.COM "Could not open log file properly."); 795*8800SReza.Sabdar@Sun.COM } 796*8800SReza.Sabdar@Sun.COM 7977917SReza.Sabdar@Sun.COM /* 7987917SReza.Sabdar@Sun.COM * Find ndmp port number to be used. If ndmpd is run as command line 7997917SReza.Sabdar@Sun.COM * and port number is supplied, use that port number. If port number is 8007917SReza.Sabdar@Sun.COM * is not supplied, find out if ndmp port property is set. If ndmp 8017917SReza.Sabdar@Sun.COM * port property is set, use that port number otherwise use the defaule 8027917SReza.Sabdar@Sun.COM * port number. 8037917SReza.Sabdar@Sun.COM */ 8047917SReza.Sabdar@Sun.COM if (ndmp_port == 0) { 8057917SReza.Sabdar@Sun.COM if ((propval = ndmpd_get_prop(NDMP_TCP_PORT)) == NULL || 8067917SReza.Sabdar@Sun.COM *propval == 0) 8077917SReza.Sabdar@Sun.COM ndmp_port = NDMPPORT; 8087917SReza.Sabdar@Sun.COM else 8097917SReza.Sabdar@Sun.COM ndmp_port = strtol(propval, 0, 0); 8107917SReza.Sabdar@Sun.COM } 8117917SReza.Sabdar@Sun.COM 8127917SReza.Sabdar@Sun.COM if (ndmp_run(ndmp_port, connection_handler) == -1) 8137917SReza.Sabdar@Sun.COM perror("ndmp_run ERROR"); 8147917SReza.Sabdar@Sun.COM 8157917SReza.Sabdar@Sun.COM ndmp_log_close_file(); 8167917SReza.Sabdar@Sun.COM } 8177917SReza.Sabdar@Sun.COM 8187917SReza.Sabdar@Sun.COM /* 8197917SReza.Sabdar@Sun.COM * connection_handler 8207917SReza.Sabdar@Sun.COM * 8217917SReza.Sabdar@Sun.COM * NDMP connection handler. 8227917SReza.Sabdar@Sun.COM * Waits for, reads, and processes NDMP requests on a connection. 8237917SReza.Sabdar@Sun.COM * 8247917SReza.Sabdar@Sun.COM * Parameters: 8257917SReza.Sabdar@Sun.COM * connection (input) - connection handle. 8267917SReza.Sabdar@Sun.COM * 8277917SReza.Sabdar@Sun.COM * Return: 8287917SReza.Sabdar@Sun.COM * void 8297917SReza.Sabdar@Sun.COM */ 8307917SReza.Sabdar@Sun.COM void 8317917SReza.Sabdar@Sun.COM connection_handler(ndmp_connection_t *connection) 8327917SReza.Sabdar@Sun.COM { 8337917SReza.Sabdar@Sun.COM static int conn_id = 1; 8347917SReza.Sabdar@Sun.COM ndmpd_session_t session; 8357917SReza.Sabdar@Sun.COM ndmp_notify_connected_request req; 8367917SReza.Sabdar@Sun.COM int connection_fd; 8377917SReza.Sabdar@Sun.COM 8387917SReza.Sabdar@Sun.COM (void) memset(&session, 0, sizeof (session)); 8397917SReza.Sabdar@Sun.COM session.ns_connection = connection; 8407917SReza.Sabdar@Sun.COM session.ns_eof = FALSE; 8417917SReza.Sabdar@Sun.COM /* 8427917SReza.Sabdar@Sun.COM * The 'protocol_version' must be 1 at first, since the client talks 8437917SReza.Sabdar@Sun.COM * to the server in version 1 then they can move to a higher 8447917SReza.Sabdar@Sun.COM * protocol version. 8457917SReza.Sabdar@Sun.COM */ 8467917SReza.Sabdar@Sun.COM session.ns_protocol_version = ndmp_ver; 8477917SReza.Sabdar@Sun.COM 8487917SReza.Sabdar@Sun.COM session.ns_scsi.sd_is_open = -1; 8497917SReza.Sabdar@Sun.COM session.ns_scsi.sd_devid = -1; 8507917SReza.Sabdar@Sun.COM 8517917SReza.Sabdar@Sun.COM session.ns_scsi.sd_sid = 0; 8527917SReza.Sabdar@Sun.COM session.ns_scsi.sd_lun = 0; 8537917SReza.Sabdar@Sun.COM session.ns_scsi.sd_valid_target_set = 0; 8547917SReza.Sabdar@Sun.COM (void) memset(session.ns_scsi.sd_adapter_name, 0, 8557917SReza.Sabdar@Sun.COM sizeof (session.ns_scsi.sd_adapter_name)); 8567917SReza.Sabdar@Sun.COM 8577917SReza.Sabdar@Sun.COM session.ns_tape.td_fd = -1; 8587917SReza.Sabdar@Sun.COM session.ns_tape.td_sid = 0; 8597917SReza.Sabdar@Sun.COM session.ns_tape.td_lun = 0; 8607917SReza.Sabdar@Sun.COM (void) memset(session.ns_tape.td_adapter_name, 0, 8617917SReza.Sabdar@Sun.COM sizeof (session.ns_tape.td_adapter_name)); 8627917SReza.Sabdar@Sun.COM session.ns_tape.td_pos = 0; 8637917SReza.Sabdar@Sun.COM session.ns_tape.td_record_count = 0; 8647917SReza.Sabdar@Sun.COM session.ns_file_handler_list = 0; 8657917SReza.Sabdar@Sun.COM 8667917SReza.Sabdar@Sun.COM (void) ndmpd_data_init(&session); 8677917SReza.Sabdar@Sun.COM ndmpd_file_history_init(&session); 8687917SReza.Sabdar@Sun.COM if (ndmpd_mover_init(&session) < 0) 8697917SReza.Sabdar@Sun.COM return; 8707917SReza.Sabdar@Sun.COM 8717917SReza.Sabdar@Sun.COM if (ndmp_lbr_init(&session) < 0) 8727917SReza.Sabdar@Sun.COM return; 8737917SReza.Sabdar@Sun.COM 8747917SReza.Sabdar@Sun.COM /* 8757917SReza.Sabdar@Sun.COM * Setup defaults here. The init functions can not set defaults 8767917SReza.Sabdar@Sun.COM * since the init functions are called by the stop request handlers 8777917SReza.Sabdar@Sun.COM * and client set variables need to persist across data operations. 8787917SReza.Sabdar@Sun.COM */ 8797917SReza.Sabdar@Sun.COM session.ns_mover.md_record_size = MAX_RECORD_SIZE; 8807917SReza.Sabdar@Sun.COM 8817917SReza.Sabdar@Sun.COM ndmp_set_client_data(connection, (void *)&session); 8827917SReza.Sabdar@Sun.COM 8837917SReza.Sabdar@Sun.COM req.reason = NDMP_CONNECTED; 8847917SReza.Sabdar@Sun.COM req.protocol_version = ndmp_ver; 8857917SReza.Sabdar@Sun.COM req.text_reason = ""; 8867917SReza.Sabdar@Sun.COM 8878193SReza.Sabdar@Sun.COM if (ndmp_send_request_lock(connection, NDMP_NOTIFY_CONNECTION_STATUS, 8887917SReza.Sabdar@Sun.COM NDMP_NO_ERR, (void *)&req, 0) < 0) { 8897917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Connection terminated"); 8907917SReza.Sabdar@Sun.COM return; 8917917SReza.Sabdar@Sun.COM } 8927917SReza.Sabdar@Sun.COM connection_fd = ndmp_get_fd(connection); 8937917SReza.Sabdar@Sun.COM 8947917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "connection_fd: %d", connection_fd); 8957917SReza.Sabdar@Sun.COM 8967917SReza.Sabdar@Sun.COM /* 8977917SReza.Sabdar@Sun.COM * Add the handler function for the connection to the DMA. 8987917SReza.Sabdar@Sun.COM */ 8997917SReza.Sabdar@Sun.COM if (ndmpd_add_file_handler(&session, (void *)&session, connection_fd, 9007917SReza.Sabdar@Sun.COM NDMPD_SELECT_MODE_READ, HC_CLIENT, connection_file_handler) != 0) { 9017917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Could not register session handler."); 9027917SReza.Sabdar@Sun.COM return; 9037917SReza.Sabdar@Sun.COM } 9047917SReza.Sabdar@Sun.COM 9057917SReza.Sabdar@Sun.COM /* 9067917SReza.Sabdar@Sun.COM * Register the connection in the list of active connections. 9077917SReza.Sabdar@Sun.COM */ 9087917SReza.Sabdar@Sun.COM if (ndmp_connect_list_add(connection, &conn_id) != 0) { 9097917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, 9107917SReza.Sabdar@Sun.COM "Could not register the session to the server."); 9117917SReza.Sabdar@Sun.COM (void) ndmpd_remove_file_handler(&session, connection_fd); 9127917SReza.Sabdar@Sun.COM return; 9137917SReza.Sabdar@Sun.COM } 9147917SReza.Sabdar@Sun.COM 9157917SReza.Sabdar@Sun.COM session.hardlink_q = hardlink_q_init(); 9167917SReza.Sabdar@Sun.COM 9177917SReza.Sabdar@Sun.COM while (session.ns_eof == FALSE) 9187917SReza.Sabdar@Sun.COM (void) ndmpd_select(&session, TRUE, HC_ALL); 9197917SReza.Sabdar@Sun.COM 9207917SReza.Sabdar@Sun.COM hardlink_q_cleanup(session.hardlink_q); 9217917SReza.Sabdar@Sun.COM 9227917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Connection terminated"); 9237917SReza.Sabdar@Sun.COM 9247917SReza.Sabdar@Sun.COM (void) ndmpd_remove_file_handler(&session, connection_fd); 9257917SReza.Sabdar@Sun.COM 9267917SReza.Sabdar@Sun.COM if (session.ns_scsi.sd_is_open != -1) { 9277917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "scsi.is_open: %d", 9287917SReza.Sabdar@Sun.COM session.ns_scsi.sd_is_open); 9297917SReza.Sabdar@Sun.COM (void) ndmp_open_list_del(session.ns_scsi.sd_adapter_name, 9307917SReza.Sabdar@Sun.COM session.ns_scsi.sd_sid, session.ns_scsi.sd_lun); 9317917SReza.Sabdar@Sun.COM } 9327917SReza.Sabdar@Sun.COM if (session.ns_tape.td_fd != -1) { 9337917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "tape.fd: %d", session.ns_tape.td_fd); 9347917SReza.Sabdar@Sun.COM (void) close(session.ns_tape.td_fd); 9357917SReza.Sabdar@Sun.COM (void) ndmp_open_list_del(session.ns_tape.td_adapter_name, 9367917SReza.Sabdar@Sun.COM session.ns_tape.td_sid, session.ns_tape.td_lun); 9377917SReza.Sabdar@Sun.COM } 9387917SReza.Sabdar@Sun.COM ndmpd_mover_shut_down(&session); 9397917SReza.Sabdar@Sun.COM ndmp_lbr_cleanup(&session); 9407917SReza.Sabdar@Sun.COM ndmpd_data_cleanup(&session); 9417917SReza.Sabdar@Sun.COM ndmpd_file_history_cleanup(&session, FALSE); 9427917SReza.Sabdar@Sun.COM ndmpd_mover_cleanup(&session); 9437917SReza.Sabdar@Sun.COM 9447917SReza.Sabdar@Sun.COM (void) ndmp_connect_list_del(connection); 9457917SReza.Sabdar@Sun.COM } 9467917SReza.Sabdar@Sun.COM 9477917SReza.Sabdar@Sun.COM 9487917SReza.Sabdar@Sun.COM /* 9497917SReza.Sabdar@Sun.COM * connection_file_handler 9507917SReza.Sabdar@Sun.COM * 9517917SReza.Sabdar@Sun.COM * ndmp_connection_t file handler function. 9527917SReza.Sabdar@Sun.COM * Called by ndmpd_select when data is available to be read on the 9537917SReza.Sabdar@Sun.COM * NDMP connection. 9547917SReza.Sabdar@Sun.COM * 9557917SReza.Sabdar@Sun.COM * Parameters: 9567917SReza.Sabdar@Sun.COM * cookie (input) - session pointer. 9577917SReza.Sabdar@Sun.COM * fd (input) - connection file descriptor. 9587917SReza.Sabdar@Sun.COM * mode (input) - select mode. 9597917SReza.Sabdar@Sun.COM * 9607917SReza.Sabdar@Sun.COM * Returns: 9617917SReza.Sabdar@Sun.COM * void. 9627917SReza.Sabdar@Sun.COM */ 9637917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 9647917SReza.Sabdar@Sun.COM static void 9657917SReza.Sabdar@Sun.COM connection_file_handler(void *cookie, int fd, ulong_t mode) 9667917SReza.Sabdar@Sun.COM { 9677917SReza.Sabdar@Sun.COM ndmpd_session_t *session = (ndmpd_session_t *)cookie; 9687917SReza.Sabdar@Sun.COM 9697917SReza.Sabdar@Sun.COM if (ndmp_process_requests(session->ns_connection) < 0) 9707917SReza.Sabdar@Sun.COM session->ns_eof = TRUE; 9717917SReza.Sabdar@Sun.COM } 9727917SReza.Sabdar@Sun.COM 9737917SReza.Sabdar@Sun.COM 9747917SReza.Sabdar@Sun.COM /* ************* private functions *************************************** */ 9757917SReza.Sabdar@Sun.COM 9767917SReza.Sabdar@Sun.COM /* 9777917SReza.Sabdar@Sun.COM * ndmp_readit 9787917SReza.Sabdar@Sun.COM * 9797917SReza.Sabdar@Sun.COM * Low level read routine called by the xdrrec library. 9807917SReza.Sabdar@Sun.COM * 9817917SReza.Sabdar@Sun.COM * Parameters: 9827917SReza.Sabdar@Sun.COM * connection (input) - connection pointer. 9837917SReza.Sabdar@Sun.COM * buf (input) - location to store received data. 9847917SReza.Sabdar@Sun.COM * len (input) - max number of bytes to read. 9857917SReza.Sabdar@Sun.COM * 9867917SReza.Sabdar@Sun.COM * Returns: 9877917SReza.Sabdar@Sun.COM * >0 - number of bytes received. 9887917SReza.Sabdar@Sun.COM * -1 - error. 9897917SReza.Sabdar@Sun.COM */ 9907917SReza.Sabdar@Sun.COM static int 9917917SReza.Sabdar@Sun.COM ndmp_readit(void *connection_handle, caddr_t buf, int len) 9927917SReza.Sabdar@Sun.COM { 9937917SReza.Sabdar@Sun.COM ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 9947917SReza.Sabdar@Sun.COM 9957917SReza.Sabdar@Sun.COM len = read(connection->conn_sock, buf, len); 9967917SReza.Sabdar@Sun.COM if (len <= 0) { 9977917SReza.Sabdar@Sun.COM /* ndmp_connection_t has been closed. */ 9987917SReza.Sabdar@Sun.COM connection->conn_eof = TRUE; 9997917SReza.Sabdar@Sun.COM return (-1); 10007917SReza.Sabdar@Sun.COM } 10017917SReza.Sabdar@Sun.COM return (len); 10027917SReza.Sabdar@Sun.COM } 10037917SReza.Sabdar@Sun.COM 10047917SReza.Sabdar@Sun.COM /* 10057917SReza.Sabdar@Sun.COM * ndmp_writeit 10067917SReza.Sabdar@Sun.COM * 10077917SReza.Sabdar@Sun.COM * Low level write routine called by the xdrrec library. 10087917SReza.Sabdar@Sun.COM * 10097917SReza.Sabdar@Sun.COM * Parameters: 10107917SReza.Sabdar@Sun.COM * connection (input) - connection pointer. 10117917SReza.Sabdar@Sun.COM * buf (input) - location to store received data. 10127917SReza.Sabdar@Sun.COM * len (input) - max number of bytes to read. 10137917SReza.Sabdar@Sun.COM * 10147917SReza.Sabdar@Sun.COM * Returns: 10157917SReza.Sabdar@Sun.COM * >0 - number of bytes sent. 10167917SReza.Sabdar@Sun.COM * -1 - error. 10177917SReza.Sabdar@Sun.COM */ 10187917SReza.Sabdar@Sun.COM static int 10197917SReza.Sabdar@Sun.COM ndmp_writeit(void *connection_handle, caddr_t buf, int len) 10207917SReza.Sabdar@Sun.COM { 10217917SReza.Sabdar@Sun.COM ndmp_connection_t *connection = (ndmp_connection_t *)connection_handle; 10227917SReza.Sabdar@Sun.COM register int n; 10237917SReza.Sabdar@Sun.COM register int cnt; 10247917SReza.Sabdar@Sun.COM 10257917SReza.Sabdar@Sun.COM for (cnt = len; cnt > 0; cnt -= n, buf += n) { 10267917SReza.Sabdar@Sun.COM if ((n = write(connection->conn_sock, buf, cnt)) < 0) { 10277917SReza.Sabdar@Sun.COM connection->conn_eof = TRUE; 10287917SReza.Sabdar@Sun.COM return (-1); 10297917SReza.Sabdar@Sun.COM } 10307917SReza.Sabdar@Sun.COM } 10317917SReza.Sabdar@Sun.COM 10327917SReza.Sabdar@Sun.COM return (len); 10337917SReza.Sabdar@Sun.COM } 10347917SReza.Sabdar@Sun.COM 10357917SReza.Sabdar@Sun.COM 10367917SReza.Sabdar@Sun.COM /* 10377917SReza.Sabdar@Sun.COM * ndmp_recv_msg 10387917SReza.Sabdar@Sun.COM * 10397917SReza.Sabdar@Sun.COM * Read the next message. 10407917SReza.Sabdar@Sun.COM * 10417917SReza.Sabdar@Sun.COM * Parameters: 10427917SReza.Sabdar@Sun.COM * connection (input) - connection pointer. 10437917SReza.Sabdar@Sun.COM * msg (output) - received message. 10447917SReza.Sabdar@Sun.COM * 10457917SReza.Sabdar@Sun.COM * Returns: 10467917SReza.Sabdar@Sun.COM * 0 - Message successfully received. 10477917SReza.Sabdar@Sun.COM * error number - Message related error. 10487917SReza.Sabdar@Sun.COM * -1 - Error decoding the message header. 10497917SReza.Sabdar@Sun.COM */ 10507917SReza.Sabdar@Sun.COM static int 10517917SReza.Sabdar@Sun.COM ndmp_recv_msg(ndmp_connection_t *connection) 10527917SReza.Sabdar@Sun.COM { 10537917SReza.Sabdar@Sun.COM bool_t(*xdr_func) (XDR *, ...) = NULL; 10547917SReza.Sabdar@Sun.COM 10557917SReza.Sabdar@Sun.COM /* Decode the header. */ 10567917SReza.Sabdar@Sun.COM connection->conn_xdrs.x_op = XDR_DECODE; 10577917SReza.Sabdar@Sun.COM (void) xdrrec_skiprecord(&connection->conn_xdrs); 10587917SReza.Sabdar@Sun.COM if (!xdr_ndmp_header(&connection->conn_xdrs, 10597917SReza.Sabdar@Sun.COM &connection->conn_msginfo.mi_hdr)) 10607917SReza.Sabdar@Sun.COM return (-1); 10617917SReza.Sabdar@Sun.COM 10627917SReza.Sabdar@Sun.COM /* Lookup info necessary for processing this message. */ 10637917SReza.Sabdar@Sun.COM if ((connection->conn_msginfo.mi_handler = ndmp_get_handler(connection, 10647917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_hdr.message)) == 0) { 10657917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "Message 0x%x not supported", 10667917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_hdr.message); 10677917SReza.Sabdar@Sun.COM return (NDMP_NOT_SUPPORTED_ERR); 10687917SReza.Sabdar@Sun.COM } 10697917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_body = 0; 10707917SReza.Sabdar@Sun.COM 10717917SReza.Sabdar@Sun.COM if (connection->conn_msginfo.mi_hdr.error != NDMP_NO_ERR) 10727917SReza.Sabdar@Sun.COM return (0); 10737917SReza.Sabdar@Sun.COM 10747917SReza.Sabdar@Sun.COM /* Determine body type */ 10757917SReza.Sabdar@Sun.COM if (connection->conn_msginfo.mi_hdr.message_type == 10767917SReza.Sabdar@Sun.COM NDMP_MESSAGE_REQUEST) { 10777917SReza.Sabdar@Sun.COM if (ndmp_check_auth_required( 10787917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_hdr.message) && 10797917SReza.Sabdar@Sun.COM !connection->conn_authorized) { 10807917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 10817917SReza.Sabdar@Sun.COM "Processing request 0x%x:connection not authorized", 10827917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_hdr.message); 10837917SReza.Sabdar@Sun.COM return (NDMP_NOT_AUTHORIZED_ERR); 10847917SReza.Sabdar@Sun.COM } 10857917SReza.Sabdar@Sun.COM if (connection->conn_msginfo.mi_handler->mh_sizeof_request > 10867917SReza.Sabdar@Sun.COM 0) { 10877917SReza.Sabdar@Sun.COM xdr_func = 10887917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_handler->mh_xdr_request; 10897917SReza.Sabdar@Sun.COM if (xdr_func == NULL) { 10907917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 10917917SReza.Sabdar@Sun.COM "Processing request 0x%x: no xdr function " 10927917SReza.Sabdar@Sun.COM "in handler table", 10937917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_hdr.message); 10947917SReza.Sabdar@Sun.COM return (NDMP_NOT_SUPPORTED_ERR); 10957917SReza.Sabdar@Sun.COM } 10967917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_body = ndmp_malloc( 10977917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_handler-> 10987917SReza.Sabdar@Sun.COM mh_sizeof_request); 10997917SReza.Sabdar@Sun.COM if (connection->conn_msginfo.mi_body == NULL) 11007917SReza.Sabdar@Sun.COM return (NDMP_NO_MEM_ERR); 11017917SReza.Sabdar@Sun.COM 11027917SReza.Sabdar@Sun.COM (void) memset(connection->conn_msginfo.mi_body, 0, 11037917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_handler-> 11047917SReza.Sabdar@Sun.COM mh_sizeof_request); 11057917SReza.Sabdar@Sun.COM } 11067917SReza.Sabdar@Sun.COM } else { 11077917SReza.Sabdar@Sun.COM if (connection->conn_msginfo.mi_handler->mh_sizeof_reply > 0) { 11087917SReza.Sabdar@Sun.COM xdr_func = 11097917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_handler->mh_xdr_reply; 11107917SReza.Sabdar@Sun.COM if (xdr_func == NULL) { 11117917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 11127917SReza.Sabdar@Sun.COM "Processing reply 0x%x: no xdr function " 11137917SReza.Sabdar@Sun.COM "in handler table", 11147917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_hdr.message); 11157917SReza.Sabdar@Sun.COM return (NDMP_NOT_SUPPORTED_ERR); 11167917SReza.Sabdar@Sun.COM } 11177917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_body = ndmp_malloc( 11187917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_handler-> 11197917SReza.Sabdar@Sun.COM mh_sizeof_reply); 11207917SReza.Sabdar@Sun.COM if (connection->conn_msginfo.mi_body == NULL) 11217917SReza.Sabdar@Sun.COM return (NDMP_NO_MEM_ERR); 11227917SReza.Sabdar@Sun.COM 11237917SReza.Sabdar@Sun.COM (void) memset(connection->conn_msginfo.mi_body, 0, 11247917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_handler-> 11257917SReza.Sabdar@Sun.COM mh_sizeof_reply); 11267917SReza.Sabdar@Sun.COM } 11277917SReza.Sabdar@Sun.COM } 11287917SReza.Sabdar@Sun.COM 11297917SReza.Sabdar@Sun.COM /* Decode message arguments if needed */ 11307917SReza.Sabdar@Sun.COM if (xdr_func) { 11317917SReza.Sabdar@Sun.COM if (!(*xdr_func)(&connection->conn_xdrs, 11327917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_body)) { 11337917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 11347917SReza.Sabdar@Sun.COM "Processing message 0x%x: error decoding arguments", 11357917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_hdr.message); 11367917SReza.Sabdar@Sun.COM free(connection->conn_msginfo.mi_body); 11377917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_body = 0; 11387917SReza.Sabdar@Sun.COM return (NDMP_XDR_DECODE_ERR); 11397917SReza.Sabdar@Sun.COM } 11407917SReza.Sabdar@Sun.COM } 11417917SReza.Sabdar@Sun.COM return (0); 11427917SReza.Sabdar@Sun.COM } 11437917SReza.Sabdar@Sun.COM 11447917SReza.Sabdar@Sun.COM /* 11457917SReza.Sabdar@Sun.COM * ndmp_process_messages 11467917SReza.Sabdar@Sun.COM * 11477917SReza.Sabdar@Sun.COM * Reads the next message into the stream buffer. 11487917SReza.Sabdar@Sun.COM * Processes messages until the stream buffer is empty. 11497917SReza.Sabdar@Sun.COM * 11507917SReza.Sabdar@Sun.COM * This function processes all data in the stream buffer before returning. 11517917SReza.Sabdar@Sun.COM * This allows functions like poll() to be used to determine when new 11527917SReza.Sabdar@Sun.COM * messages have arrived. If only some of the messages in the stream buffer 11537917SReza.Sabdar@Sun.COM * were processed and then poll was called, poll() could block waiting for 11547917SReza.Sabdar@Sun.COM * a message that had already been received and read into the stream buffer. 11557917SReza.Sabdar@Sun.COM * 11567917SReza.Sabdar@Sun.COM * This function processes both request and reply messages. 11577917SReza.Sabdar@Sun.COM * Request messages are dispatched using the appropriate function from the 11587917SReza.Sabdar@Sun.COM * message handling table. 11597917SReza.Sabdar@Sun.COM * Only one reply messages may be pending receipt at a time. 11607917SReza.Sabdar@Sun.COM * A reply message, if received, is placed in connection->conn_msginfo 11617917SReza.Sabdar@Sun.COM * before returning to the caller. 11627917SReza.Sabdar@Sun.COM * Errors are reported if a reply is received but not expected or if 11637917SReza.Sabdar@Sun.COM * more than one reply message is received 11647917SReza.Sabdar@Sun.COM * 11657917SReza.Sabdar@Sun.COM * Parameters: 11667917SReza.Sabdar@Sun.COM * connection (input) - connection pointer. 11677917SReza.Sabdar@Sun.COM * reply_expected (output) - TRUE - a reply message is expected. 11687917SReza.Sabdar@Sun.COM * FALSE - no reply message is expected and 11697917SReza.Sabdar@Sun.COM * an error will be reported if a reply 11707917SReza.Sabdar@Sun.COM * is received. 11717917SReza.Sabdar@Sun.COM * 11727917SReza.Sabdar@Sun.COM * Returns: 11737917SReza.Sabdar@Sun.COM * NDMP_PROC_REP_ERR - 1 or more messages successfully processed, 11747917SReza.Sabdar@Sun.COM * error processing reply message. 11757917SReza.Sabdar@Sun.COM * NDMP_PROC_REP_ERR - 1 or more messages successfully processed, 11767917SReza.Sabdar@Sun.COM * reply seen. 11777917SReza.Sabdar@Sun.COM * NDMP_PROC_REP_ERR - 1 or more messages successfully processed, 11787917SReza.Sabdar@Sun.COM * no reply seen. 11797917SReza.Sabdar@Sun.COM * NDMP_PROC_REP_ERR - error; connection no longer established. 11807917SReza.Sabdar@Sun.COM * 11817917SReza.Sabdar@Sun.COM * Notes: 11827917SReza.Sabdar@Sun.COM * If the peer is generating a large number of requests, a caller 11837917SReza.Sabdar@Sun.COM * looking for a reply will be blocked while the requests are handled. 11847917SReza.Sabdar@Sun.COM * This is because this function does not return until the stream 11857917SReza.Sabdar@Sun.COM * buffer is empty. 11867917SReza.Sabdar@Sun.COM * Code needs to be added to allow a return if the stream buffer 11877917SReza.Sabdar@Sun.COM * is not empty but there is data available on the socket. This will 11887917SReza.Sabdar@Sun.COM * prevent poll() from blocking and prevent a caller looking for a reply 11897917SReza.Sabdar@Sun.COM * from getting blocked by a bunch of requests. 11907917SReza.Sabdar@Sun.COM */ 11917917SReza.Sabdar@Sun.COM static int 11927917SReza.Sabdar@Sun.COM ndmp_process_messages(ndmp_connection_t *connection, boolean_t reply_expected) 11937917SReza.Sabdar@Sun.COM { 11947917SReza.Sabdar@Sun.COM msg_info_t reply_msginfo; 11957917SReza.Sabdar@Sun.COM boolean_t reply_read = FALSE; 11967917SReza.Sabdar@Sun.COM boolean_t reply_error = FALSE; 11977917SReza.Sabdar@Sun.COM int err; 11987917SReza.Sabdar@Sun.COM 11997917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "reply_expected: %s", 12007917SReza.Sabdar@Sun.COM reply_expected == TRUE ? "TRUE" : "FALSE"); 12017917SReza.Sabdar@Sun.COM 12027917SReza.Sabdar@Sun.COM (void) memset((void *)&reply_msginfo, 0, sizeof (msg_info_t)); 12037917SReza.Sabdar@Sun.COM 12047917SReza.Sabdar@Sun.COM do { 12057917SReza.Sabdar@Sun.COM (void) memset((void *)&connection->conn_msginfo, 0, 12067917SReza.Sabdar@Sun.COM sizeof (msg_info_t)); 12077917SReza.Sabdar@Sun.COM 12087917SReza.Sabdar@Sun.COM if ((err = ndmp_recv_msg(connection)) != NDMP_NO_ERR) { 12097917SReza.Sabdar@Sun.COM if (connection->conn_eof) { 12107917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "detected eof"); 12117917SReza.Sabdar@Sun.COM return (NDMP_PROC_ERR); 12127917SReza.Sabdar@Sun.COM } 12137917SReza.Sabdar@Sun.COM if (err < 1) { 12147917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "error decoding header"); 12157917SReza.Sabdar@Sun.COM 12167917SReza.Sabdar@Sun.COM /* 12177917SReza.Sabdar@Sun.COM * Error occurred decoding the header. 12187917SReza.Sabdar@Sun.COM * Don't send a reply since we don't know 12197917SReza.Sabdar@Sun.COM * the message or if the message was even 12207917SReza.Sabdar@Sun.COM * a request message. To be safe, assume 12217917SReza.Sabdar@Sun.COM * that the message was a reply if a reply 12227917SReza.Sabdar@Sun.COM * was expected. Need to do this to prevent 12237917SReza.Sabdar@Sun.COM * hanging ndmp_send_request() waiting for a 12247917SReza.Sabdar@Sun.COM * reply. Don't set reply_read so that the 12257917SReza.Sabdar@Sun.COM * reply will be processed if it is received 12267917SReza.Sabdar@Sun.COM * later. 12277917SReza.Sabdar@Sun.COM */ 12287917SReza.Sabdar@Sun.COM if (reply_read == FALSE) 12297917SReza.Sabdar@Sun.COM reply_error = TRUE; 12307917SReza.Sabdar@Sun.COM 12317917SReza.Sabdar@Sun.COM continue; 12327917SReza.Sabdar@Sun.COM } 12337917SReza.Sabdar@Sun.COM if (connection->conn_msginfo.mi_hdr.message_type 12347917SReza.Sabdar@Sun.COM != NDMP_MESSAGE_REQUEST) { 12357917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "received reply: 0x%x", 12367917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_hdr.message); 12377917SReza.Sabdar@Sun.COM 12387917SReza.Sabdar@Sun.COM if (reply_expected == FALSE || 12397917SReza.Sabdar@Sun.COM reply_read == TRUE) 12407917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 12417917SReza.Sabdar@Sun.COM "Unexpected reply message: 0x%x", 12427917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_hdr. 12437917SReza.Sabdar@Sun.COM message); 12447917SReza.Sabdar@Sun.COM 12457917SReza.Sabdar@Sun.COM ndmp_free_message((ndmp_connection_t *) 12467917SReza.Sabdar@Sun.COM connection); 12477917SReza.Sabdar@Sun.COM 12487917SReza.Sabdar@Sun.COM if (reply_read == FALSE) { 12497917SReza.Sabdar@Sun.COM reply_read = TRUE; 12507917SReza.Sabdar@Sun.COM reply_error = TRUE; 12517917SReza.Sabdar@Sun.COM } 12527917SReza.Sabdar@Sun.COM continue; 12537917SReza.Sabdar@Sun.COM } 12547917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "received request: 0x%x", 12557917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_hdr.message); 12567917SReza.Sabdar@Sun.COM 12577917SReza.Sabdar@Sun.COM (void) ndmp_send_response((ndmp_connection_t *) 12587917SReza.Sabdar@Sun.COM connection, err, NULL); 12597917SReza.Sabdar@Sun.COM ndmp_free_message((ndmp_connection_t *)connection); 12607917SReza.Sabdar@Sun.COM continue; 12617917SReza.Sabdar@Sun.COM } 12627917SReza.Sabdar@Sun.COM if (connection->conn_msginfo.mi_hdr.message_type 12637917SReza.Sabdar@Sun.COM != NDMP_MESSAGE_REQUEST) { 12647917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "received reply: 0x%x", 12657917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_hdr.message); 12667917SReza.Sabdar@Sun.COM 12677917SReza.Sabdar@Sun.COM if (reply_expected == FALSE || reply_read == TRUE) { 12687917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, 12697917SReza.Sabdar@Sun.COM "Unexpected reply message: 0x%x", 12707917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_hdr.message); 12717917SReza.Sabdar@Sun.COM ndmp_free_message((ndmp_connection_t *) 12727917SReza.Sabdar@Sun.COM connection); 12737917SReza.Sabdar@Sun.COM continue; 12747917SReza.Sabdar@Sun.COM } 12757917SReza.Sabdar@Sun.COM reply_read = TRUE; 12767917SReza.Sabdar@Sun.COM reply_msginfo = connection->conn_msginfo; 12777917SReza.Sabdar@Sun.COM continue; 12787917SReza.Sabdar@Sun.COM } 12797917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "received request: 0x%x", 12807917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_hdr.message); 12817917SReza.Sabdar@Sun.COM 12827917SReza.Sabdar@Sun.COM /* 12837917SReza.Sabdar@Sun.COM * The following is needed to catch an improperly constructed 12847917SReza.Sabdar@Sun.COM * handler table or to deal with an NDMP client that is not 12857917SReza.Sabdar@Sun.COM * conforming to the negotiated protocol version. 12867917SReza.Sabdar@Sun.COM */ 12877917SReza.Sabdar@Sun.COM if (connection->conn_msginfo.mi_handler->mh_func == NULL) { 12887917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "No handler for message 0x%x", 12897917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_hdr.message); 12907917SReza.Sabdar@Sun.COM 12917917SReza.Sabdar@Sun.COM (void) ndmp_send_response((ndmp_connection_t *) 12927917SReza.Sabdar@Sun.COM connection, NDMP_NOT_SUPPORTED_ERR, NULL); 12937917SReza.Sabdar@Sun.COM ndmp_free_message((ndmp_connection_t *)connection); 12947917SReza.Sabdar@Sun.COM continue; 12957917SReza.Sabdar@Sun.COM } 12967917SReza.Sabdar@Sun.COM /* 12977917SReza.Sabdar@Sun.COM * Call the handler function. 12987917SReza.Sabdar@Sun.COM * The handler will send any necessary reply. 12997917SReza.Sabdar@Sun.COM */ 13007917SReza.Sabdar@Sun.COM (*connection->conn_msginfo.mi_handler->mh_func) (connection, 13017917SReza.Sabdar@Sun.COM connection->conn_msginfo.mi_body); 13027917SReza.Sabdar@Sun.COM 13037917SReza.Sabdar@Sun.COM ndmp_free_message((ndmp_connection_t *)connection); 13047917SReza.Sabdar@Sun.COM 13057917SReza.Sabdar@Sun.COM } while (xdrrec_eof(&connection->conn_xdrs) == FALSE && 13067917SReza.Sabdar@Sun.COM connection->conn_eof == FALSE); 13077917SReza.Sabdar@Sun.COM 13087917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_DEBUG, "no more messages in stream buffer"); 13097917SReza.Sabdar@Sun.COM 13107917SReza.Sabdar@Sun.COM if (connection->conn_eof == TRUE) { 13117917SReza.Sabdar@Sun.COM if (reply_msginfo.mi_body) 13127917SReza.Sabdar@Sun.COM free(reply_msginfo.mi_body); 13137917SReza.Sabdar@Sun.COM return (NDMP_PROC_ERR); 13147917SReza.Sabdar@Sun.COM } 13157917SReza.Sabdar@Sun.COM if (reply_error) { 13167917SReza.Sabdar@Sun.COM if (reply_msginfo.mi_body) 13177917SReza.Sabdar@Sun.COM free(reply_msginfo.mi_body); 13187917SReza.Sabdar@Sun.COM return (NDMP_PROC_REP_ERR); 13197917SReza.Sabdar@Sun.COM } 13207917SReza.Sabdar@Sun.COM if (reply_read) { 13217917SReza.Sabdar@Sun.COM connection->conn_msginfo = reply_msginfo; 13227917SReza.Sabdar@Sun.COM return (NDMP_PROC_MSG); 13237917SReza.Sabdar@Sun.COM } 13247917SReza.Sabdar@Sun.COM return (NDMP_PROC_REP); 13257917SReza.Sabdar@Sun.COM } 13267917SReza.Sabdar@Sun.COM 13277917SReza.Sabdar@Sun.COM 13287917SReza.Sabdar@Sun.COM /* 13297917SReza.Sabdar@Sun.COM * ndmp_get_interface 13307917SReza.Sabdar@Sun.COM * 13317917SReza.Sabdar@Sun.COM * Return the NDMP interface (e.g. config, scsi, tape) for the 13327917SReza.Sabdar@Sun.COM * specific message. 13337917SReza.Sabdar@Sun.COM * 13347917SReza.Sabdar@Sun.COM * Parameters: 13357917SReza.Sabdar@Sun.COM * message (input) - message number. 13367917SReza.Sabdar@Sun.COM * 13377917SReza.Sabdar@Sun.COM * Returns: 13387917SReza.Sabdar@Sun.COM * NULL - message not found. 13397917SReza.Sabdar@Sun.COM * pointer to handler info. 13407917SReza.Sabdar@Sun.COM */ 13417917SReza.Sabdar@Sun.COM static ndmp_handler_t * 13427917SReza.Sabdar@Sun.COM ndmp_get_interface(ndmp_message message) 13437917SReza.Sabdar@Sun.COM { 13447917SReza.Sabdar@Sun.COM ndmp_handler_t *ni = &ndmp_msghdl_tab[(message >> 8) % INT_MAXCMD]; 13457917SReza.Sabdar@Sun.COM 13467917SReza.Sabdar@Sun.COM if ((message & 0xff) >= ni->hd_cnt) 13477917SReza.Sabdar@Sun.COM return (NULL); 13487917SReza.Sabdar@Sun.COM 13497917SReza.Sabdar@Sun.COM /* Sanity check */ 13507917SReza.Sabdar@Sun.COM if (ni->hd_msgs[message & 0xff].hm_message != message) 13517917SReza.Sabdar@Sun.COM return (NULL); 13527917SReza.Sabdar@Sun.COM 13537917SReza.Sabdar@Sun.COM return (ni); 13547917SReza.Sabdar@Sun.COM } 13557917SReza.Sabdar@Sun.COM 13567917SReza.Sabdar@Sun.COM /* 13577917SReza.Sabdar@Sun.COM * ndmp_get_handler 13587917SReza.Sabdar@Sun.COM * 13597917SReza.Sabdar@Sun.COM * Return the handler info for the specified NDMP message. 13607917SReza.Sabdar@Sun.COM * 13617917SReza.Sabdar@Sun.COM * Parameters: 13627917SReza.Sabdar@Sun.COM * connection (input) - connection pointer. 13637917SReza.Sabdar@Sun.COM * message (input) - message number. 13647917SReza.Sabdar@Sun.COM * 13657917SReza.Sabdar@Sun.COM * Returns: 13667917SReza.Sabdar@Sun.COM * NULL - message not found. 13677917SReza.Sabdar@Sun.COM * pointer to handler info. 13687917SReza.Sabdar@Sun.COM */ 13697917SReza.Sabdar@Sun.COM static ndmp_msg_handler_t * 13707917SReza.Sabdar@Sun.COM ndmp_get_handler(ndmp_connection_t *connection, ndmp_message message) 13717917SReza.Sabdar@Sun.COM { 13727917SReza.Sabdar@Sun.COM ndmp_msg_handler_t *handler = NULL; 13737917SReza.Sabdar@Sun.COM 13747917SReza.Sabdar@Sun.COM ndmp_handler_t *ni = ndmp_get_interface(message); 13757917SReza.Sabdar@Sun.COM int ver = connection->conn_version; 13767917SReza.Sabdar@Sun.COM 13777917SReza.Sabdar@Sun.COM if (ni) 13787917SReza.Sabdar@Sun.COM handler = &ni->hd_msgs[message & 0xff].hm_msg_v[ver - 2]; 13797917SReza.Sabdar@Sun.COM 13807917SReza.Sabdar@Sun.COM return (handler); 13817917SReza.Sabdar@Sun.COM } 13827917SReza.Sabdar@Sun.COM 13837917SReza.Sabdar@Sun.COM /* 13847917SReza.Sabdar@Sun.COM * ndmp_check_auth_required 13857917SReza.Sabdar@Sun.COM * 13867917SReza.Sabdar@Sun.COM * Check if the connection needs to be authenticated before 13877917SReza.Sabdar@Sun.COM * this message is being processed. 13887917SReza.Sabdar@Sun.COM * 13897917SReza.Sabdar@Sun.COM * Parameters: 13907917SReza.Sabdar@Sun.COM * message (input) - message number. 13917917SReza.Sabdar@Sun.COM * 13927917SReza.Sabdar@Sun.COM * Returns: 13937917SReza.Sabdar@Sun.COM * TRUE - required 13947917SReza.Sabdar@Sun.COM * FALSE - not required 13957917SReza.Sabdar@Sun.COM */ 13967917SReza.Sabdar@Sun.COM static boolean_t 13977917SReza.Sabdar@Sun.COM ndmp_check_auth_required(ndmp_message message) 13987917SReza.Sabdar@Sun.COM { 13997917SReza.Sabdar@Sun.COM boolean_t auth_req = FALSE; 14007917SReza.Sabdar@Sun.COM ndmp_handler_t *ni = ndmp_get_interface(message); 14017917SReza.Sabdar@Sun.COM 14027917SReza.Sabdar@Sun.COM if (ni) 14037917SReza.Sabdar@Sun.COM auth_req = ni->hd_msgs[message & 0xff].hm_auth_required; 14047917SReza.Sabdar@Sun.COM 14057917SReza.Sabdar@Sun.COM return (auth_req); 14067917SReza.Sabdar@Sun.COM } 14077917SReza.Sabdar@Sun.COM 14087917SReza.Sabdar@Sun.COM /* 14097917SReza.Sabdar@Sun.COM * tcp_accept 14107917SReza.Sabdar@Sun.COM * 14117917SReza.Sabdar@Sun.COM * A wrapper around accept for retrying and getting the IP address 14127917SReza.Sabdar@Sun.COM * 14137917SReza.Sabdar@Sun.COM * Parameters: 14147917SReza.Sabdar@Sun.COM * listen_sock (input) - the socket for listening 14157917SReza.Sabdar@Sun.COM * inaddr_p (output) - the IP address of peer connection 14167917SReza.Sabdar@Sun.COM * 14177917SReza.Sabdar@Sun.COM * Returns: 14187917SReza.Sabdar@Sun.COM * socket for the accepted connection 14197917SReza.Sabdar@Sun.COM * -1: error 14207917SReza.Sabdar@Sun.COM */ 14217917SReza.Sabdar@Sun.COM int 14227917SReza.Sabdar@Sun.COM tcp_accept(int listen_sock, unsigned int *inaddr_p) 14237917SReza.Sabdar@Sun.COM { 14247917SReza.Sabdar@Sun.COM struct sockaddr_in sin; 14257917SReza.Sabdar@Sun.COM int sock, i; 14267917SReza.Sabdar@Sun.COM int try; 14277917SReza.Sabdar@Sun.COM 14287917SReza.Sabdar@Sun.COM for (try = 0; try < 3; try++) { 14297917SReza.Sabdar@Sun.COM i = sizeof (sin); 14307917SReza.Sabdar@Sun.COM sock = accept(listen_sock, (struct sockaddr *)&sin, &i); 14317917SReza.Sabdar@Sun.COM if (sock < 0) { 14327917SReza.Sabdar@Sun.COM continue; 14337917SReza.Sabdar@Sun.COM } 14347917SReza.Sabdar@Sun.COM *inaddr_p = sin.sin_addr.s_addr; 14357917SReza.Sabdar@Sun.COM return (sock); 14367917SReza.Sabdar@Sun.COM } 14377917SReza.Sabdar@Sun.COM return (-1); 14387917SReza.Sabdar@Sun.COM } 14397917SReza.Sabdar@Sun.COM 14407917SReza.Sabdar@Sun.COM 14417917SReza.Sabdar@Sun.COM /* 14427917SReza.Sabdar@Sun.COM * tcp_get_peer 14437917SReza.Sabdar@Sun.COM * 14447917SReza.Sabdar@Sun.COM * Get the peer IP address for a connection 14457917SReza.Sabdar@Sun.COM * 14467917SReza.Sabdar@Sun.COM * Parameters: 14477917SReza.Sabdar@Sun.COM * sock (input) - the active socket 14487917SReza.Sabdar@Sun.COM * inaddr_p (output) - the IP address of peer connection 14497917SReza.Sabdar@Sun.COM * port_p (output) - the port number of peer connection 14507917SReza.Sabdar@Sun.COM * 14517917SReza.Sabdar@Sun.COM * Returns: 14527917SReza.Sabdar@Sun.COM * socket for the accepted connection 14537917SReza.Sabdar@Sun.COM * -1: error 14547917SReza.Sabdar@Sun.COM */ 14557917SReza.Sabdar@Sun.COM int 14567917SReza.Sabdar@Sun.COM tcp_get_peer(int sock, unsigned int *inaddr_p, int *port_p) 14577917SReza.Sabdar@Sun.COM { 14587917SReza.Sabdar@Sun.COM struct sockaddr_in sin; 14597917SReza.Sabdar@Sun.COM int i, rc; 14607917SReza.Sabdar@Sun.COM 14617917SReza.Sabdar@Sun.COM i = sizeof (sin); 14627917SReza.Sabdar@Sun.COM rc = getpeername(sock, (struct sockaddr *)&sin, &i); 14637917SReza.Sabdar@Sun.COM if (rc != 0) 14647917SReza.Sabdar@Sun.COM return (-1); 14657917SReza.Sabdar@Sun.COM 14667917SReza.Sabdar@Sun.COM if (inaddr_p) 14677917SReza.Sabdar@Sun.COM *inaddr_p = sin.sin_addr.s_addr; 14687917SReza.Sabdar@Sun.COM 14697917SReza.Sabdar@Sun.COM if (port_p) 14707917SReza.Sabdar@Sun.COM *port_p = ntohs(sin.sin_port); 14717917SReza.Sabdar@Sun.COM 14727917SReza.Sabdar@Sun.COM return (sock); 14737917SReza.Sabdar@Sun.COM 14747917SReza.Sabdar@Sun.COM } 14757917SReza.Sabdar@Sun.COM 14767917SReza.Sabdar@Sun.COM /* 14777917SReza.Sabdar@Sun.COM * gethostaddr 14787917SReza.Sabdar@Sun.COM * 14797917SReza.Sabdar@Sun.COM * Get the IP address string of the current host 14807917SReza.Sabdar@Sun.COM * 14817917SReza.Sabdar@Sun.COM * Parameters: 14827917SReza.Sabdar@Sun.COM * void 14837917SReza.Sabdar@Sun.COM * 14847917SReza.Sabdar@Sun.COM * Returns: 14857917SReza.Sabdar@Sun.COM * IP address 14867917SReza.Sabdar@Sun.COM * NULL: error 14877917SReza.Sabdar@Sun.COM */ 14887917SReza.Sabdar@Sun.COM char * 14897917SReza.Sabdar@Sun.COM gethostaddr(void) 14907917SReza.Sabdar@Sun.COM { 14917917SReza.Sabdar@Sun.COM static char s[MAXHOSTNAMELEN]; 14927917SReza.Sabdar@Sun.COM struct hostent *h; 14937917SReza.Sabdar@Sun.COM struct in_addr in; 14947917SReza.Sabdar@Sun.COM char *p; 14957917SReza.Sabdar@Sun.COM 14967917SReza.Sabdar@Sun.COM if (gethostname(s, sizeof (s)) == -1) 14977917SReza.Sabdar@Sun.COM return (NULL); 14987917SReza.Sabdar@Sun.COM 14997917SReza.Sabdar@Sun.COM if ((h = gethostbyname(s)) == NULL) 15007917SReza.Sabdar@Sun.COM return (NULL); 15017917SReza.Sabdar@Sun.COM 15027917SReza.Sabdar@Sun.COM p = h->h_addr_list[0]; 15037917SReza.Sabdar@Sun.COM (void) memcpy(&in.s_addr, p, sizeof (in.s_addr)); 15047917SReza.Sabdar@Sun.COM return (inet_ntoa(in)); 15057917SReza.Sabdar@Sun.COM } 15067917SReza.Sabdar@Sun.COM 15077917SReza.Sabdar@Sun.COM /* 15087917SReza.Sabdar@Sun.COM * ndmpd_audit_backup 15097917SReza.Sabdar@Sun.COM * 15107917SReza.Sabdar@Sun.COM * Generate AUE_ndmp_backup audit record 15117917SReza.Sabdar@Sun.COM */ 15127917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 15137917SReza.Sabdar@Sun.COM void 15147917SReza.Sabdar@Sun.COM ndmpd_audit_backup(ndmp_connection_t *conn, 15157917SReza.Sabdar@Sun.COM char *path, int dest, char *local_path, int result) 15167917SReza.Sabdar@Sun.COM { 15177917SReza.Sabdar@Sun.COM adt_event_data_t *event; 15187917SReza.Sabdar@Sun.COM 15197917SReza.Sabdar@Sun.COM if ((event = adt_alloc_event(conn->conn_ah, ADT_ndmp_backup)) == NULL) { 15207917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Audit failure: %m."); 15217917SReza.Sabdar@Sun.COM return; 15227917SReza.Sabdar@Sun.COM } 15237917SReza.Sabdar@Sun.COM event->adt_ndmp_backup.source = path; 15247917SReza.Sabdar@Sun.COM 15257917SReza.Sabdar@Sun.COM if (dest == NDMP_ADDR_LOCAL) { 15267917SReza.Sabdar@Sun.COM event->adt_ndmp_backup.local_dest = local_path; 15277917SReza.Sabdar@Sun.COM } else { 15287917SReza.Sabdar@Sun.COM event->adt_ndmp_backup.remote_dest = conn->conn_sock; 15297917SReza.Sabdar@Sun.COM } 15307917SReza.Sabdar@Sun.COM 15317917SReza.Sabdar@Sun.COM if (result == 0) { 15327917SReza.Sabdar@Sun.COM if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) 15337917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Audit failure: %m."); 15347917SReza.Sabdar@Sun.COM } else { 15357917SReza.Sabdar@Sun.COM if (adt_put_event(event, ADT_FAILURE, result) != 0) 15367917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Audit failure: %m."); 15377917SReza.Sabdar@Sun.COM } 15387917SReza.Sabdar@Sun.COM 15397917SReza.Sabdar@Sun.COM adt_free_event(event); 15407917SReza.Sabdar@Sun.COM } 15417917SReza.Sabdar@Sun.COM 15427917SReza.Sabdar@Sun.COM 15437917SReza.Sabdar@Sun.COM /* 15447917SReza.Sabdar@Sun.COM * ndmpd_audit_restore 15457917SReza.Sabdar@Sun.COM * 15467917SReza.Sabdar@Sun.COM * Generate AUE_ndmp_restore audit record 15477917SReza.Sabdar@Sun.COM */ 15487917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 15497917SReza.Sabdar@Sun.COM void 15507917SReza.Sabdar@Sun.COM ndmpd_audit_restore(ndmp_connection_t *conn, 15517917SReza.Sabdar@Sun.COM char *path, int dest, char *local_path, int result) 15527917SReza.Sabdar@Sun.COM { 15537917SReza.Sabdar@Sun.COM adt_event_data_t *event; 15547917SReza.Sabdar@Sun.COM 15557917SReza.Sabdar@Sun.COM if ((event = adt_alloc_event(conn->conn_ah, 15567917SReza.Sabdar@Sun.COM ADT_ndmp_restore)) == NULL) { 15577917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Audit failure: %m."); 15587917SReza.Sabdar@Sun.COM return; 15597917SReza.Sabdar@Sun.COM } 15607917SReza.Sabdar@Sun.COM event->adt_ndmp_restore.destination = path; 15617917SReza.Sabdar@Sun.COM 15627917SReza.Sabdar@Sun.COM if (dest == NDMP_ADDR_LOCAL) { 15637917SReza.Sabdar@Sun.COM event->adt_ndmp_restore.local_source = local_path; 15647917SReza.Sabdar@Sun.COM } else { 15657917SReza.Sabdar@Sun.COM event->adt_ndmp_restore.remote_source = conn->conn_sock; 15667917SReza.Sabdar@Sun.COM } 15677917SReza.Sabdar@Sun.COM 15687917SReza.Sabdar@Sun.COM if (result == 0) { 15697917SReza.Sabdar@Sun.COM if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) 15707917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Audit failure: %m."); 15717917SReza.Sabdar@Sun.COM } else { 15727917SReza.Sabdar@Sun.COM if (adt_put_event(event, ADT_FAILURE, result) != 0) 15737917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Audit failure: %m."); 15747917SReza.Sabdar@Sun.COM } 15757917SReza.Sabdar@Sun.COM 15767917SReza.Sabdar@Sun.COM adt_free_event(event); 15777917SReza.Sabdar@Sun.COM } 15787917SReza.Sabdar@Sun.COM 15797917SReza.Sabdar@Sun.COM 15807917SReza.Sabdar@Sun.COM /* 15817917SReza.Sabdar@Sun.COM * ndmpd_audit_connect 15827917SReza.Sabdar@Sun.COM * 15837917SReza.Sabdar@Sun.COM * Generate AUE_ndmp_connect audit record 15847917SReza.Sabdar@Sun.COM */ 15857917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 15867917SReza.Sabdar@Sun.COM void 15877917SReza.Sabdar@Sun.COM ndmpd_audit_connect(ndmp_connection_t *conn, int result) 15887917SReza.Sabdar@Sun.COM { 15897917SReza.Sabdar@Sun.COM adt_event_data_t *event; 15907917SReza.Sabdar@Sun.COM adt_termid_t *termid; 15917917SReza.Sabdar@Sun.COM 15927917SReza.Sabdar@Sun.COM if (adt_load_termid(conn->conn_sock, &termid) != 0) { 15937917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Audit failure: %m."); 15947917SReza.Sabdar@Sun.COM return; 15957917SReza.Sabdar@Sun.COM } 15967917SReza.Sabdar@Sun.COM 15977917SReza.Sabdar@Sun.COM if (adt_set_user(conn->conn_ah, ADT_NO_ATTRIB, ADT_NO_ATTRIB, 15987917SReza.Sabdar@Sun.COM ADT_NO_ATTRIB, ADT_NO_ATTRIB, termid, ADT_NEW) != 0) { 15997917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Audit failure: %m."); 16007917SReza.Sabdar@Sun.COM free(termid); 16017917SReza.Sabdar@Sun.COM return; 16027917SReza.Sabdar@Sun.COM } 16037917SReza.Sabdar@Sun.COM free(termid); 16047917SReza.Sabdar@Sun.COM 16057917SReza.Sabdar@Sun.COM if ((event = adt_alloc_event(conn->conn_ah, 16067917SReza.Sabdar@Sun.COM ADT_ndmp_connect)) == NULL) { 16077917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Audit failure: %m."); 16087917SReza.Sabdar@Sun.COM return; 16097917SReza.Sabdar@Sun.COM } 16107917SReza.Sabdar@Sun.COM 16117917SReza.Sabdar@Sun.COM if (result == 0) { 16127917SReza.Sabdar@Sun.COM if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) 16137917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Audit failure: %m."); 16147917SReza.Sabdar@Sun.COM } else { 16157917SReza.Sabdar@Sun.COM if (adt_put_event(event, ADT_FAILURE, result) != 0) 16167917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Audit failure: %m."); 16177917SReza.Sabdar@Sun.COM } 16187917SReza.Sabdar@Sun.COM 16197917SReza.Sabdar@Sun.COM adt_free_event(event); 16207917SReza.Sabdar@Sun.COM } 16217917SReza.Sabdar@Sun.COM 16227917SReza.Sabdar@Sun.COM 16237917SReza.Sabdar@Sun.COM /* 16247917SReza.Sabdar@Sun.COM * ndmpd_audit_disconnect 16257917SReza.Sabdar@Sun.COM * 16267917SReza.Sabdar@Sun.COM * Generate AUE_ndmp_disconnect audit record 16277917SReza.Sabdar@Sun.COM */ 16287917SReza.Sabdar@Sun.COM /*ARGSUSED*/ 16297917SReza.Sabdar@Sun.COM void 16307917SReza.Sabdar@Sun.COM ndmpd_audit_disconnect(ndmp_connection_t *conn) 16317917SReza.Sabdar@Sun.COM { 16327917SReza.Sabdar@Sun.COM adt_event_data_t *event; 16337917SReza.Sabdar@Sun.COM 16347917SReza.Sabdar@Sun.COM if ((event = adt_alloc_event(conn->conn_ah, 16357917SReza.Sabdar@Sun.COM ADT_ndmp_disconnect)) == NULL) { 16367917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Audit failure: %m."); 16377917SReza.Sabdar@Sun.COM return; 16387917SReza.Sabdar@Sun.COM } 16397917SReza.Sabdar@Sun.COM if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0) 16407917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Audit failure: %m."); 16417917SReza.Sabdar@Sun.COM 16427917SReza.Sabdar@Sun.COM adt_free_event(event); 16437917SReza.Sabdar@Sun.COM } 16447917SReza.Sabdar@Sun.COM 16457917SReza.Sabdar@Sun.COM void * 16467917SReza.Sabdar@Sun.COM ndmp_malloc(size_t size) 16477917SReza.Sabdar@Sun.COM { 16487917SReza.Sabdar@Sun.COM void *data; 16497917SReza.Sabdar@Sun.COM 16507917SReza.Sabdar@Sun.COM if ((data = calloc(1, size)) == NULL) { 16517917SReza.Sabdar@Sun.COM NDMP_LOG(LOG_ERR, "Out of memory."); 16527917SReza.Sabdar@Sun.COM } 16537917SReza.Sabdar@Sun.COM 16547917SReza.Sabdar@Sun.COM return (data); 16557917SReza.Sabdar@Sun.COM } 1656