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