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