xref: /onnv-gate/usr/src/cmd/ndmpd/ndmp/ndmpd_comm.c (revision 13023:7a57e737278a)
17917SReza.Sabdar@Sun.COM /*
212186SJanice.Chang@Sun.COM  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
37917SReza.Sabdar@Sun.COM  */
47917SReza.Sabdar@Sun.COM 
57917SReza.Sabdar@Sun.COM /*
67917SReza.Sabdar@Sun.COM  * BSD 3 Clause License
77917SReza.Sabdar@Sun.COM  *
87917SReza.Sabdar@Sun.COM  * Copyright (c) 2007, The Storage Networking Industry Association.
97917SReza.Sabdar@Sun.COM  *
107917SReza.Sabdar@Sun.COM  * Redistribution and use in source and binary forms, with or without
117917SReza.Sabdar@Sun.COM  * modification, are permitted provided that the following conditions
127917SReza.Sabdar@Sun.COM  * are met:
137917SReza.Sabdar@Sun.COM  * 	- Redistributions of source code must retain the above copyright
147917SReza.Sabdar@Sun.COM  *	  notice, this list of conditions and the following disclaimer.
157917SReza.Sabdar@Sun.COM  *
167917SReza.Sabdar@Sun.COM  * 	- Redistributions in binary form must reproduce the above copyright
177917SReza.Sabdar@Sun.COM  *	  notice, this list of conditions and the following disclaimer in
187917SReza.Sabdar@Sun.COM  *	  the documentation and/or other materials provided with the
197917SReza.Sabdar@Sun.COM  *	  distribution.
207917SReza.Sabdar@Sun.COM  *
217917SReza.Sabdar@Sun.COM  *	- Neither the name of The Storage Networking Industry Association (SNIA)
227917SReza.Sabdar@Sun.COM  *	  nor the names of its contributors may be used to endorse or promote
237917SReza.Sabdar@Sun.COM  *	  products derived from this software without specific prior written
247917SReza.Sabdar@Sun.COM  *	  permission.
257917SReza.Sabdar@Sun.COM  *
267917SReza.Sabdar@Sun.COM  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
277917SReza.Sabdar@Sun.COM  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
287917SReza.Sabdar@Sun.COM  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
297917SReza.Sabdar@Sun.COM  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
307917SReza.Sabdar@Sun.COM  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
317917SReza.Sabdar@Sun.COM  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
327917SReza.Sabdar@Sun.COM  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
337917SReza.Sabdar@Sun.COM  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
347917SReza.Sabdar@Sun.COM  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
357917SReza.Sabdar@Sun.COM  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
367917SReza.Sabdar@Sun.COM  * POSSIBILITY OF SUCH DAMAGE.
377917SReza.Sabdar@Sun.COM  */
387917SReza.Sabdar@Sun.COM /* Copyright (c) 2007, The Storage Networking Industry Association. */
397917SReza.Sabdar@Sun.COM /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
407917SReza.Sabdar@Sun.COM 
417917SReza.Sabdar@Sun.COM #include <sys/types.h>
427917SReza.Sabdar@Sun.COM #include <sys/socket.h>
437917SReza.Sabdar@Sun.COM #include <sys/time.h>
447917SReza.Sabdar@Sun.COM #include <sys/uio.h>
457917SReza.Sabdar@Sun.COM #include <unistd.h>
467917SReza.Sabdar@Sun.COM #include <string.h>
477917SReza.Sabdar@Sun.COM #include <stdlib.h>
487917SReza.Sabdar@Sun.COM #include <errno.h>
497917SReza.Sabdar@Sun.COM #include <netdb.h>
507917SReza.Sabdar@Sun.COM #include <netinet/in.h>
517917SReza.Sabdar@Sun.COM #include <arpa/inet.h>
52*13023SReza.Sabdar@Sun.COM #include <libinetutil.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
xdr_ndmp_header(XDR * xdrs,ndmp_header * objp)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 *
ndmp_create_connection(void)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
ndmp_destroy_connection(ndmp_connection_t * connection_handle)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
ndmp_close(ndmp_connection_t * connection_handle)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
ndmp_start_worker(ndmpd_worker_arg_t * argp)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
ndmp_run(ulong_t port,ndmp_con_handler_func_t con_handler_func)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 *
ndmpd_worker(void * ptarg)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
ndmp_process_requests(ndmp_connection_t * connection_handle)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
ndmp_send_request(ndmp_connection_t * connection_handle,ndmp_message message,ndmp_error err,void * request_data,void ** reply)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
ndmp_send_request_lock(ndmp_connection_t * connection_handle,ndmp_message message,ndmp_error err,void * request_data,void ** reply)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
ndmp_send_response(ndmp_connection_t * connection_handle,ndmp_error err,void * reply)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
ndmp_free_message(ndmp_connection_t * connection_handle)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
ndmp_get_fd(ndmp_connection_t * connection_handle)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
ndmp_set_client_data(ndmp_connection_t * connection_handle,void * client_data)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 *
ndmp_get_client_data(ndmp_connection_t * connection_handle)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
ndmp_set_version(ndmp_connection_t * connection_handle,ushort_t version)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
ndmp_get_version(ndmp_connection_t * connection_handle)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
ndmp_set_authorized(ndmp_connection_t * connection_handle,boolean_t authorized)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
ndmpd_main(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();
7928800SReza.Sabdar@Sun.COM 	if (ndmp_log_open_file() != 0) {
7938800SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR,
7948800SReza.Sabdar@Sun.COM 		    "Could not open log file properly.");
7958800SReza.Sabdar@Sun.COM 	}
7968800SReza.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
connection_handler(ndmp_connection_t * connection)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
connection_file_handler(void * cookie,int fd,ulong_t mode)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
ndmp_readit(void * connection_handle,caddr_t buf,int len)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
ndmp_writeit(void * connection_handle,caddr_t buf,int len)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
ndmp_recv_msg(ndmp_connection_t * connection)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
ndmp_process_messages(ndmp_connection_t * connection,boolean_t reply_expected)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 *
ndmp_get_interface(ndmp_message message)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 *
ndmp_get_handler(ndmp_connection_t * connection,ndmp_message message)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
ndmp_check_auth_required(ndmp_message message)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
tcp_accept(int listen_sock,unsigned int * inaddr_p)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
tcp_get_peer(int sock,unsigned int * inaddr_p,int * port_p)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 *
gethostaddr(void)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 
1507*13023SReza.Sabdar@Sun.COM 
1508*13023SReza.Sabdar@Sun.COM /*
1509*13023SReza.Sabdar@Sun.COM  * get_default_nic_addr
1510*13023SReza.Sabdar@Sun.COM  *
1511*13023SReza.Sabdar@Sun.COM  * Get the IP address of the default NIC
1512*13023SReza.Sabdar@Sun.COM  */
1513*13023SReza.Sabdar@Sun.COM char *
get_default_nic_addr(void)1514*13023SReza.Sabdar@Sun.COM get_default_nic_addr(void)
1515*13023SReza.Sabdar@Sun.COM {
1516*13023SReza.Sabdar@Sun.COM 	struct ifaddrlist *al = NULL;
1517*13023SReza.Sabdar@Sun.COM 	char errmsg[ERRBUFSIZE];
1518*13023SReza.Sabdar@Sun.COM 	struct in_addr addr;
1519*13023SReza.Sabdar@Sun.COM 	int nifs;
1520*13023SReza.Sabdar@Sun.COM 
1521*13023SReza.Sabdar@Sun.COM 	nifs = ifaddrlist(&al, AF_INET, LIFC_EXTERNAL_SOURCE, errmsg);
1522*13023SReza.Sabdar@Sun.COM 	if (nifs <= 0)
1523*13023SReza.Sabdar@Sun.COM 		return (NULL);
1524*13023SReza.Sabdar@Sun.COM 
1525*13023SReza.Sabdar@Sun.COM 	/* pick the first interface's address */
1526*13023SReza.Sabdar@Sun.COM 	addr = al[0].addr.addr;
1527*13023SReza.Sabdar@Sun.COM 	free(al);
1528*13023SReza.Sabdar@Sun.COM 
1529*13023SReza.Sabdar@Sun.COM 	return (inet_ntoa(IN_ADDR(addr.s_addr)));
1530*13023SReza.Sabdar@Sun.COM }
1531*13023SReza.Sabdar@Sun.COM 
1532*13023SReza.Sabdar@Sun.COM 
15337917SReza.Sabdar@Sun.COM /*
15347917SReza.Sabdar@Sun.COM  * ndmpd_audit_backup
15357917SReza.Sabdar@Sun.COM  *
15367917SReza.Sabdar@Sun.COM  * Generate AUE_ndmp_backup audit record
15377917SReza.Sabdar@Sun.COM  */
15387917SReza.Sabdar@Sun.COM /*ARGSUSED*/
15397917SReza.Sabdar@Sun.COM void
ndmpd_audit_backup(ndmp_connection_t * conn,char * path,int dest,char * local_path,int result)15407917SReza.Sabdar@Sun.COM ndmpd_audit_backup(ndmp_connection_t *conn,
15417917SReza.Sabdar@Sun.COM     char *path, int dest, char *local_path, int result)
15427917SReza.Sabdar@Sun.COM {
15437917SReza.Sabdar@Sun.COM 	adt_event_data_t *event;
15447917SReza.Sabdar@Sun.COM 
15457917SReza.Sabdar@Sun.COM 	if ((event = adt_alloc_event(conn->conn_ah, ADT_ndmp_backup)) == NULL) {
15467917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Audit failure: %m.");
15477917SReza.Sabdar@Sun.COM 		return;
15487917SReza.Sabdar@Sun.COM 	}
15497917SReza.Sabdar@Sun.COM 	event->adt_ndmp_backup.source = path;
15507917SReza.Sabdar@Sun.COM 
15517917SReza.Sabdar@Sun.COM 	if (dest == NDMP_ADDR_LOCAL) {
15527917SReza.Sabdar@Sun.COM 		event->adt_ndmp_backup.local_dest = local_path;
15537917SReza.Sabdar@Sun.COM 	} else {
15547917SReza.Sabdar@Sun.COM 		event->adt_ndmp_backup.remote_dest = conn->conn_sock;
15557917SReza.Sabdar@Sun.COM 	}
15567917SReza.Sabdar@Sun.COM 
15577917SReza.Sabdar@Sun.COM 	if (result == 0) {
15587917SReza.Sabdar@Sun.COM 		if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0)
15597917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_ERR, "Audit failure: %m.");
15607917SReza.Sabdar@Sun.COM 	} else {
15617917SReza.Sabdar@Sun.COM 		if (adt_put_event(event, ADT_FAILURE, result) != 0)
15627917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_ERR, "Audit failure: %m.");
15637917SReza.Sabdar@Sun.COM 	}
15647917SReza.Sabdar@Sun.COM 
15657917SReza.Sabdar@Sun.COM 	adt_free_event(event);
15667917SReza.Sabdar@Sun.COM }
15677917SReza.Sabdar@Sun.COM 
15687917SReza.Sabdar@Sun.COM 
15697917SReza.Sabdar@Sun.COM /*
15707917SReza.Sabdar@Sun.COM  * ndmpd_audit_restore
15717917SReza.Sabdar@Sun.COM  *
15727917SReza.Sabdar@Sun.COM  * Generate AUE_ndmp_restore audit record
15737917SReza.Sabdar@Sun.COM  */
15747917SReza.Sabdar@Sun.COM /*ARGSUSED*/
15757917SReza.Sabdar@Sun.COM void
ndmpd_audit_restore(ndmp_connection_t * conn,char * path,int dest,char * local_path,int result)15767917SReza.Sabdar@Sun.COM ndmpd_audit_restore(ndmp_connection_t *conn,
15777917SReza.Sabdar@Sun.COM     char *path, int dest, char *local_path, int result)
15787917SReza.Sabdar@Sun.COM {
15797917SReza.Sabdar@Sun.COM 	adt_event_data_t *event;
15807917SReza.Sabdar@Sun.COM 
15817917SReza.Sabdar@Sun.COM 	if ((event = adt_alloc_event(conn->conn_ah,
15827917SReza.Sabdar@Sun.COM 	    ADT_ndmp_restore)) == NULL) {
15837917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Audit failure: %m.");
15847917SReza.Sabdar@Sun.COM 		return;
15857917SReza.Sabdar@Sun.COM 	}
15867917SReza.Sabdar@Sun.COM 	event->adt_ndmp_restore.destination = path;
15877917SReza.Sabdar@Sun.COM 
15887917SReza.Sabdar@Sun.COM 	if (dest == NDMP_ADDR_LOCAL) {
15897917SReza.Sabdar@Sun.COM 		event->adt_ndmp_restore.local_source = local_path;
15907917SReza.Sabdar@Sun.COM 	} else {
15917917SReza.Sabdar@Sun.COM 		event->adt_ndmp_restore.remote_source = conn->conn_sock;
15927917SReza.Sabdar@Sun.COM 	}
15937917SReza.Sabdar@Sun.COM 
15947917SReza.Sabdar@Sun.COM 	if (result == 0) {
15957917SReza.Sabdar@Sun.COM 		if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0)
15967917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_ERR, "Audit failure: %m.");
15977917SReza.Sabdar@Sun.COM 	} else {
15987917SReza.Sabdar@Sun.COM 		if (adt_put_event(event, ADT_FAILURE, result) != 0)
15997917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_ERR, "Audit failure: %m.");
16007917SReza.Sabdar@Sun.COM 	}
16017917SReza.Sabdar@Sun.COM 
16027917SReza.Sabdar@Sun.COM 	adt_free_event(event);
16037917SReza.Sabdar@Sun.COM }
16047917SReza.Sabdar@Sun.COM 
16057917SReza.Sabdar@Sun.COM 
16067917SReza.Sabdar@Sun.COM /*
16077917SReza.Sabdar@Sun.COM  * ndmpd_audit_connect
16087917SReza.Sabdar@Sun.COM  *
16097917SReza.Sabdar@Sun.COM  * Generate AUE_ndmp_connect audit record
16107917SReza.Sabdar@Sun.COM  */
16117917SReza.Sabdar@Sun.COM /*ARGSUSED*/
16127917SReza.Sabdar@Sun.COM void
ndmpd_audit_connect(ndmp_connection_t * conn,int result)16137917SReza.Sabdar@Sun.COM ndmpd_audit_connect(ndmp_connection_t *conn, int result)
16147917SReza.Sabdar@Sun.COM {
16157917SReza.Sabdar@Sun.COM 	adt_event_data_t *event;
16167917SReza.Sabdar@Sun.COM 	adt_termid_t *termid;
16177917SReza.Sabdar@Sun.COM 
16187917SReza.Sabdar@Sun.COM 	if (adt_load_termid(conn->conn_sock, &termid) != 0) {
16197917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Audit failure: %m.");
16207917SReza.Sabdar@Sun.COM 		return;
16217917SReza.Sabdar@Sun.COM 	}
16227917SReza.Sabdar@Sun.COM 
16237917SReza.Sabdar@Sun.COM 	if (adt_set_user(conn->conn_ah, ADT_NO_ATTRIB, ADT_NO_ATTRIB,
16247917SReza.Sabdar@Sun.COM 	    ADT_NO_ATTRIB, ADT_NO_ATTRIB, termid, ADT_NEW) != 0) {
16257917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Audit failure: %m.");
16267917SReza.Sabdar@Sun.COM 		free(termid);
16277917SReza.Sabdar@Sun.COM 		return;
16287917SReza.Sabdar@Sun.COM 	}
16297917SReza.Sabdar@Sun.COM 	free(termid);
16307917SReza.Sabdar@Sun.COM 
16317917SReza.Sabdar@Sun.COM 	if ((event = adt_alloc_event(conn->conn_ah,
16327917SReza.Sabdar@Sun.COM 	    ADT_ndmp_connect)) == NULL) {
16337917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Audit failure: %m.");
16347917SReza.Sabdar@Sun.COM 		return;
16357917SReza.Sabdar@Sun.COM 	}
16367917SReza.Sabdar@Sun.COM 
16377917SReza.Sabdar@Sun.COM 	if (result == 0) {
16387917SReza.Sabdar@Sun.COM 		if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0)
16397917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_ERR, "Audit failure: %m.");
16407917SReza.Sabdar@Sun.COM 	} else {
16417917SReza.Sabdar@Sun.COM 		if (adt_put_event(event, ADT_FAILURE, result) != 0)
16427917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_ERR, "Audit failure: %m.");
16437917SReza.Sabdar@Sun.COM 	}
16447917SReza.Sabdar@Sun.COM 
16457917SReza.Sabdar@Sun.COM 	adt_free_event(event);
16467917SReza.Sabdar@Sun.COM }
16477917SReza.Sabdar@Sun.COM 
16487917SReza.Sabdar@Sun.COM 
16497917SReza.Sabdar@Sun.COM /*
16507917SReza.Sabdar@Sun.COM  * ndmpd_audit_disconnect
16517917SReza.Sabdar@Sun.COM  *
16527917SReza.Sabdar@Sun.COM  * Generate AUE_ndmp_disconnect audit record
16537917SReza.Sabdar@Sun.COM  */
16547917SReza.Sabdar@Sun.COM /*ARGSUSED*/
16557917SReza.Sabdar@Sun.COM void
ndmpd_audit_disconnect(ndmp_connection_t * conn)16567917SReza.Sabdar@Sun.COM ndmpd_audit_disconnect(ndmp_connection_t *conn)
16577917SReza.Sabdar@Sun.COM {
16587917SReza.Sabdar@Sun.COM 	adt_event_data_t *event;
16597917SReza.Sabdar@Sun.COM 
16607917SReza.Sabdar@Sun.COM 	if ((event = adt_alloc_event(conn->conn_ah,
16617917SReza.Sabdar@Sun.COM 	    ADT_ndmp_disconnect)) == NULL) {
16627917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Audit failure: %m.");
16637917SReza.Sabdar@Sun.COM 		return;
16647917SReza.Sabdar@Sun.COM 	}
16657917SReza.Sabdar@Sun.COM 	if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS) != 0)
16667917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Audit failure: %m.");
16677917SReza.Sabdar@Sun.COM 
16687917SReza.Sabdar@Sun.COM 	adt_free_event(event);
16697917SReza.Sabdar@Sun.COM }
16707917SReza.Sabdar@Sun.COM 
16717917SReza.Sabdar@Sun.COM void *
ndmp_malloc(size_t size)16727917SReza.Sabdar@Sun.COM ndmp_malloc(size_t size)
16737917SReza.Sabdar@Sun.COM {
16747917SReza.Sabdar@Sun.COM 	void *data;
16757917SReza.Sabdar@Sun.COM 
16767917SReza.Sabdar@Sun.COM 	if ((data = calloc(1, size)) == NULL) {
16777917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Out of memory.");
16787917SReza.Sabdar@Sun.COM 	}
16797917SReza.Sabdar@Sun.COM 
16807917SReza.Sabdar@Sun.COM 	return (data);
16817917SReza.Sabdar@Sun.COM }
168212186SJanice.Chang@Sun.COM 
168312186SJanice.Chang@Sun.COM /*
168412186SJanice.Chang@Sun.COM  * get_backup_path_v3
168512186SJanice.Chang@Sun.COM  *
168612186SJanice.Chang@Sun.COM  * Get the backup path from the NDMP environment variables.
168712186SJanice.Chang@Sun.COM  *
168812186SJanice.Chang@Sun.COM  * Parameters:
168912186SJanice.Chang@Sun.COM  *   params (input) - pointer to the parameters structure.
169012186SJanice.Chang@Sun.COM  *
169112186SJanice.Chang@Sun.COM  * Returns:
169212186SJanice.Chang@Sun.COM  *   The backup path: if anything is specified
169312186SJanice.Chang@Sun.COM  *   NULL: Otherwise
169412186SJanice.Chang@Sun.COM  */
169512186SJanice.Chang@Sun.COM char *
get_backup_path_v3(ndmpd_module_params_t * params)169612186SJanice.Chang@Sun.COM get_backup_path_v3(ndmpd_module_params_t *params)
169712186SJanice.Chang@Sun.COM {
169812186SJanice.Chang@Sun.COM 	char *bkpath;
169912186SJanice.Chang@Sun.COM 
170012186SJanice.Chang@Sun.COM 	bkpath = MOD_GETENV(params, "PREFIX");
170112186SJanice.Chang@Sun.COM 	if (!bkpath)
170212186SJanice.Chang@Sun.COM 		bkpath = MOD_GETENV(params, "FILESYSTEM");
170312186SJanice.Chang@Sun.COM 
170412186SJanice.Chang@Sun.COM 
170512186SJanice.Chang@Sun.COM 	if (!bkpath) {
170612186SJanice.Chang@Sun.COM 		MOD_LOGV3(params, NDMP_LOG_ERROR,
170712186SJanice.Chang@Sun.COM 		    "Backup path not defined.\n");
170812186SJanice.Chang@Sun.COM 	} else {
170912186SJanice.Chang@Sun.COM 		NDMP_LOG(LOG_DEBUG, "bkpath: \"%s\"", bkpath);
171012186SJanice.Chang@Sun.COM 	}
171112186SJanice.Chang@Sun.COM 
171212186SJanice.Chang@Sun.COM 	return (bkpath);
171312186SJanice.Chang@Sun.COM }
171412186SJanice.Chang@Sun.COM 
171512186SJanice.Chang@Sun.COM /*
171612186SJanice.Chang@Sun.COM  * get_backup_path
171712186SJanice.Chang@Sun.COM  *
171812186SJanice.Chang@Sun.COM  * Find the backup path from the environment variables (v2)
171912186SJanice.Chang@Sun.COM  */
172012186SJanice.Chang@Sun.COM char *
get_backup_path_v2(ndmpd_module_params_t * params)172112186SJanice.Chang@Sun.COM get_backup_path_v2(ndmpd_module_params_t *params)
172212186SJanice.Chang@Sun.COM {
172312186SJanice.Chang@Sun.COM 	char *bkpath;
172412186SJanice.Chang@Sun.COM 
172512186SJanice.Chang@Sun.COM 	bkpath = MOD_GETENV(params, "PREFIX");
172612186SJanice.Chang@Sun.COM 	if (bkpath == NULL)
172712186SJanice.Chang@Sun.COM 		bkpath = MOD_GETENV(params, "FILESYSTEM");
172812186SJanice.Chang@Sun.COM 
172912186SJanice.Chang@Sun.COM 	if (bkpath == NULL) {
173012186SJanice.Chang@Sun.COM 		MOD_LOG(params, "Error: restore path not specified.\n");
173112186SJanice.Chang@Sun.COM 		return (NULL);
173212186SJanice.Chang@Sun.COM 	}
173312186SJanice.Chang@Sun.COM 
173412186SJanice.Chang@Sun.COM 	if (*bkpath != '/') {
173512186SJanice.Chang@Sun.COM 		MOD_LOG(params, "Error: relative backup path not allowed.\n");
173612186SJanice.Chang@Sun.COM 		return (NULL);
173712186SJanice.Chang@Sun.COM 	}
173812186SJanice.Chang@Sun.COM 
173912186SJanice.Chang@Sun.COM 	return (bkpath);
174012186SJanice.Chang@Sun.COM }
1741