xref: /illumos-gate/usr/src/cmd/ndmpd/ndmp/ndmpd_util.c (revision 65451a03349bdb7f4bf79a8f29d4065772e01cae)
12654012fSReza Sabdar /*
28c4f9701SJanice Chang  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
32654012fSReza Sabdar  */
42654012fSReza Sabdar 
52654012fSReza Sabdar /*
62654012fSReza Sabdar  * BSD 3 Clause License
72654012fSReza Sabdar  *
82654012fSReza Sabdar  * Copyright (c) 2007, The Storage Networking Industry Association.
92654012fSReza Sabdar  *
102654012fSReza Sabdar  * Redistribution and use in source and binary forms, with or without
112654012fSReza Sabdar  * modification, are permitted provided that the following conditions
122654012fSReza Sabdar  * are met:
132654012fSReza Sabdar  * 	- Redistributions of source code must retain the above copyright
142654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer.
152654012fSReza Sabdar  *
162654012fSReza Sabdar  * 	- Redistributions in binary form must reproduce the above copyright
172654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer in
182654012fSReza Sabdar  *	  the documentation and/or other materials provided with the
192654012fSReza Sabdar  *	  distribution.
202654012fSReza Sabdar  *
212654012fSReza Sabdar  *	- Neither the name of The Storage Networking Industry Association (SNIA)
222654012fSReza Sabdar  *	  nor the names of its contributors may be used to endorse or promote
232654012fSReza Sabdar  *	  products derived from this software without specific prior written
242654012fSReza Sabdar  *	  permission.
252654012fSReza Sabdar  *
262654012fSReza Sabdar  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
272654012fSReza Sabdar  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
282654012fSReza Sabdar  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
292654012fSReza Sabdar  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
302654012fSReza Sabdar  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
312654012fSReza Sabdar  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
322654012fSReza Sabdar  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
332654012fSReza Sabdar  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
342654012fSReza Sabdar  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
352654012fSReza Sabdar  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
362654012fSReza Sabdar  * POSSIBILITY OF SUCH DAMAGE.
372654012fSReza Sabdar  */
382654012fSReza Sabdar /* Copyright (c) 2007, The Storage Networking Industry Association. */
392654012fSReza Sabdar /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
402654012fSReza Sabdar 
412654012fSReza Sabdar #include <sys/types.h>
422654012fSReza Sabdar #include <sys/socket.h>
432654012fSReza Sabdar #include <assert.h>
442654012fSReza Sabdar #include <ctype.h>
452654012fSReza Sabdar #include <errno.h>
462654012fSReza Sabdar #include <stdio.h>
472654012fSReza Sabdar #include <stdlib.h>
482654012fSReza Sabdar #include <unistd.h>
492654012fSReza Sabdar #include <strings.h>
502654012fSReza Sabdar #include <time.h>
512654012fSReza Sabdar #include "ndmpd.h"
522654012fSReza Sabdar #include <bitmap.h>
532654012fSReza Sabdar #include <sys/queue.h>
542654012fSReza Sabdar #include <sys/socket.h>
552654012fSReza Sabdar #include <netinet/in.h>
562654012fSReza Sabdar #include <netinet/tcp.h>
572654012fSReza Sabdar #include <arpa/inet.h>
582654012fSReza Sabdar #include <sys/socketvar.h>
592654012fSReza Sabdar #include <net/if.h>
602654012fSReza Sabdar #include <netdb.h>
612654012fSReza Sabdar #include <sys/filio.h>
622654012fSReza Sabdar #include <sys/mtio.h>
632654012fSReza Sabdar #include <sys/scsi/impl/uscsi.h>
642654012fSReza Sabdar #include <sys/scsi/scsi.h>
652654012fSReza Sabdar #include "tlm.h"
662654012fSReza Sabdar 
672654012fSReza Sabdar /*
682654012fSReza Sabdar  * Mutex to protect Nlp
692654012fSReza Sabdar  */
702654012fSReza Sabdar mutex_t nlp_mtx;
712654012fSReza Sabdar 
722654012fSReza Sabdar /*
732654012fSReza Sabdar  * Patchable socket buffer sizes in kilobytes.
742654012fSReza Sabdar  * ssb: send buffer size.
752654012fSReza Sabdar  * rsb: receive buffer size.
762654012fSReza Sabdar  */
772654012fSReza Sabdar int ndmp_sbs = 60;
782654012fSReza Sabdar int ndmp_rbs = 60;
792654012fSReza Sabdar 
802654012fSReza Sabdar 
812654012fSReza Sabdar /*
822654012fSReza Sabdar  * Force to backup all the intermediate directories leading to an object
832654012fSReza Sabdar  * to be backed up in 'dump' format backup.
842654012fSReza Sabdar  */
852654012fSReza Sabdar boolean_t ndmp_dump_path_node = FALSE;
862654012fSReza Sabdar 
872654012fSReza Sabdar 
882654012fSReza Sabdar /*
892654012fSReza Sabdar  * Force to backup all the intermediate directories leading to an object
902654012fSReza Sabdar  * to be backed up in 'tar' format backup.
912654012fSReza Sabdar  */
922654012fSReza Sabdar boolean_t ndmp_tar_path_node = FALSE;
932654012fSReza Sabdar 
942654012fSReza Sabdar 
952654012fSReza Sabdar /*
962654012fSReza Sabdar  * Should the 'st_ctime' be ignored during incremental level backup?
972654012fSReza Sabdar  */
982654012fSReza Sabdar boolean_t ndmp_ignore_ctime = FALSE;
992654012fSReza Sabdar 
1002654012fSReza Sabdar /*
1012654012fSReza Sabdar  * Should the 'st_lmtime' be included during incremental level backup?
1022654012fSReza Sabdar  */
1032654012fSReza Sabdar boolean_t ndmp_include_lmtime = FALSE;
1042654012fSReza Sabdar 
1052654012fSReza Sabdar /*
1062654012fSReza Sabdar  * Force to send the file history node entries along with the file history
1072654012fSReza Sabdar  * dir entries for all directories containing the changed files to the client
1082654012fSReza Sabdar  * for incremental backup.
1092654012fSReza Sabdar  *
1102654012fSReza Sabdar  * Note: This variable is added to support Bakbone Software's Netvault DMA
1112654012fSReza Sabdar  * which expects to get the FH ADD NODES for all upper directories which
1122654012fSReza Sabdar  * contain the changed files in incremental backup along with the FH ADD DIRS.
1132654012fSReza Sabdar  */
1142654012fSReza Sabdar boolean_t ndmp_fhinode = FALSE;
1152654012fSReza Sabdar 
1162654012fSReza Sabdar /*
1172654012fSReza Sabdar  * Maximum permitted sequence number in the token-based backup.  The
1182654012fSReza Sabdar  * value of this variable can be changed by the administrator and is
1192654012fSReza Sabdar  * saved in the NDMP configuration file.
1202654012fSReza Sabdar  */
1212654012fSReza Sabdar static int ndmp_max_tok_seq = NDMP_MAX_TOKSEQ;
1222654012fSReza Sabdar 
1232654012fSReza Sabdar /*
1242654012fSReza Sabdar  * Force backup directories in incremental backups.  If the
1252654012fSReza Sabdar  * directory is not modified itself, it's not backed up by
1262654012fSReza Sabdar  * default.
1272654012fSReza Sabdar  */
1282654012fSReza Sabdar int ndmp_force_bk_dirs = 0;
1292654012fSReza Sabdar 
1302654012fSReza Sabdar /*
1312654012fSReza Sabdar  * Keeps track of the open SCSI (including tape and robot) devices.
1322654012fSReza Sabdar  * When a SCSI device is opened its name must be added to this list and
1332654012fSReza Sabdar  * when it's closed its name must be removed from this list.  The main
1342654012fSReza Sabdar  * purpose of this list is the robot device.  If the robot devices are not
1352654012fSReza Sabdar  * attached in SASD layer, Local Backup won't see them. If they are
1362654012fSReza Sabdar  * attached and we open the robot devices, then wrong commands are sent
1372654012fSReza Sabdar  * to robot by SASD since it assumes that the robot is a tape (sequential
1382654012fSReza Sabdar  * access) device.
1392654012fSReza Sabdar  */
1402654012fSReza Sabdar struct open_list {
1412654012fSReza Sabdar 	LIST_ENTRY(open_list) ol_q;
1422654012fSReza Sabdar 	int ol_nref;
1432654012fSReza Sabdar 	char *ol_devnm;
1442654012fSReza Sabdar 	int ol_sid;
1452654012fSReza Sabdar 	int ol_lun;
1462654012fSReza Sabdar 	int ol_fd;
1472654012fSReza Sabdar 	ndmp_connection_t *cl_conn;
1482654012fSReza Sabdar };
1492654012fSReza Sabdar LIST_HEAD(ol_head, open_list);
1502654012fSReza Sabdar 
1512654012fSReza Sabdar 
1522654012fSReza Sabdar /*
1532654012fSReza Sabdar  * Head of the opened SCSI devices list.
1542654012fSReza Sabdar  */
1552654012fSReza Sabdar static struct ol_head ol_head;
1562654012fSReza Sabdar 
1572654012fSReza Sabdar mutex_t ol_mutex = DEFAULTMUTEX;
1582654012fSReza Sabdar 
1592654012fSReza Sabdar 
1602654012fSReza Sabdar /*
1612654012fSReza Sabdar  * List of things to be exluded from backup.
1622654012fSReza Sabdar  */
1632654012fSReza Sabdar static char *exls[] = {
1642654012fSReza Sabdar 	EXCL_PROC,
1652654012fSReza Sabdar 	EXCL_TMP,
1662654012fSReza Sabdar 	NULL, /* reserved for a copy of the "backup.directory" */
1672654012fSReza Sabdar 	NULL
1682654012fSReza Sabdar };
1692654012fSReza Sabdar 
1702654012fSReza Sabdar 
1712654012fSReza Sabdar /*
1722654012fSReza Sabdar  * The counter for creating unique names with "ndmp.%d" format.
1732654012fSReza Sabdar  */
1742654012fSReza Sabdar #define	NDMP_RCF_BASENAME	"ndmp."
1752654012fSReza Sabdar static int ndmp_job_cnt = 0;
1762654012fSReza Sabdar 
1772654012fSReza Sabdar static int scsi_test_unit_ready(int dev_id);
1782654012fSReza Sabdar 
1792654012fSReza Sabdar /*
1802654012fSReza Sabdar  * ndmpd_add_file_handler
1812654012fSReza Sabdar  *
1822654012fSReza Sabdar  * Adds a file handler to the file handler list.
1832654012fSReza Sabdar  * The file handler list is used by ndmpd_api_dispatch.
1842654012fSReza Sabdar  *
1852654012fSReza Sabdar  * Parameters:
1862654012fSReza Sabdar  *   session (input) - session pointer.
1872654012fSReza Sabdar  *   cookie  (input) - opaque data to be passed to file hander when called.
1882654012fSReza Sabdar  *   fd      (input) - file descriptor.
1892654012fSReza Sabdar  *   mode    (input) - bitmask of the following:
1902654012fSReza Sabdar  *		     1 = watch file for ready for reading
1912654012fSReza Sabdar  *		     2 = watch file for ready for writing
1922654012fSReza Sabdar  *		     4 = watch file for exception
1932654012fSReza Sabdar  *   class   (input) - handler class. (HC_CLIENT, HC_MOVER, HC_MODULE)
1942654012fSReza Sabdar  *   func    (input) - function to call when the file meets one of the
1952654012fSReza Sabdar  *		     conditions specified by mode.
1962654012fSReza Sabdar  *
1972654012fSReza Sabdar  * Returns:
1982654012fSReza Sabdar  *   0 - success.
1992654012fSReza Sabdar  *  -1 - error.
2002654012fSReza Sabdar  */
2012654012fSReza Sabdar int
2022654012fSReza Sabdar ndmpd_add_file_handler(ndmpd_session_t *session, void *cookie, int fd,
2032654012fSReza Sabdar     ulong_t mode, ulong_t class, ndmpd_file_handler_func_t *func)
2042654012fSReza Sabdar {
2052654012fSReza Sabdar 	ndmpd_file_handler_t *new;
2062654012fSReza Sabdar 
2072654012fSReza Sabdar 	new = ndmp_malloc(sizeof (ndmpd_file_handler_t));
2082654012fSReza Sabdar 	if (new == 0)
2092654012fSReza Sabdar 		return (-1);
2102654012fSReza Sabdar 
2112654012fSReza Sabdar 	new->fh_cookie = cookie;
2122654012fSReza Sabdar 	new->fh_fd = fd;
2132654012fSReza Sabdar 	new->fh_mode = mode;
2142654012fSReza Sabdar 	new->fh_class = class;
2152654012fSReza Sabdar 	new->fh_func = func;
2162654012fSReza Sabdar 	new->fh_next = session->ns_file_handler_list;
2172654012fSReza Sabdar 	session->ns_file_handler_list = new;
2182654012fSReza Sabdar 	return (0);
2192654012fSReza Sabdar }
2202654012fSReza Sabdar 
2212654012fSReza Sabdar 
2222654012fSReza Sabdar /*
2232654012fSReza Sabdar  * ndmpd_remove_file_handler
2242654012fSReza Sabdar  *
2252654012fSReza Sabdar  * Removes a file handler from the file handler list.
2262654012fSReza Sabdar  *
2272654012fSReza Sabdar  * Parameters:
2282654012fSReza Sabdar  *   session (input) - session pointer.
2292654012fSReza Sabdar  *   fd      (input) - file descriptor.
2302654012fSReza Sabdar  *
2312654012fSReza Sabdar  * Returns:
2322654012fSReza Sabdar  *   0 - success.
2332654012fSReza Sabdar  *  -1 - error.
2342654012fSReza Sabdar  */
2352654012fSReza Sabdar int
2362654012fSReza Sabdar ndmpd_remove_file_handler(ndmpd_session_t *session, int fd)
2372654012fSReza Sabdar {
2382654012fSReza Sabdar 	ndmpd_file_handler_t **last;
2392654012fSReza Sabdar 	ndmpd_file_handler_t *handler;
2402654012fSReza Sabdar 
2412654012fSReza Sabdar 	last = &session->ns_file_handler_list;
2422654012fSReza Sabdar 	while (*last != 0) {
2432654012fSReza Sabdar 		handler = *last;
2442654012fSReza Sabdar 
2452654012fSReza Sabdar 		if (handler->fh_fd == fd) {
2462654012fSReza Sabdar 			*last = handler->fh_next;
2472654012fSReza Sabdar 			(void) free(handler);
2482654012fSReza Sabdar 			return (1);
2492654012fSReza Sabdar 		}
2502654012fSReza Sabdar 		last = &handler->fh_next;
2512654012fSReza Sabdar 	}
2522654012fSReza Sabdar 
2532654012fSReza Sabdar 	return (0);
2542654012fSReza Sabdar }
2552654012fSReza Sabdar 
2562654012fSReza Sabdar 
2572654012fSReza Sabdar /*
2582654012fSReza Sabdar  * ndmp_connection_closed
2592654012fSReza Sabdar  *
2602654012fSReza Sabdar  * If the connection closed or not.
2612654012fSReza Sabdar  *
2622654012fSReza Sabdar  * Parameters:
2632654012fSReza Sabdar  *   fd (input) : file descriptor
2642654012fSReza Sabdar  *
2652654012fSReza Sabdar  * Returns:
2662654012fSReza Sabdar  *   0  - connection is still valid
2672654012fSReza Sabdar  *   1  - connection is not valid anymore
2682654012fSReza Sabdar  *   -1 - Internal kernel error
2692654012fSReza Sabdar  */
2702654012fSReza Sabdar int
2712654012fSReza Sabdar ndmp_connection_closed(int fd)
2722654012fSReza Sabdar {
2732654012fSReza Sabdar 	fd_set fds;
2742654012fSReza Sabdar 	int closed, ret;
2752654012fSReza Sabdar 	struct timeval timeout;
2762654012fSReza Sabdar 
2772654012fSReza Sabdar 	if (fd < 0) /* We are not using the mover */
2782654012fSReza Sabdar 		return (-1);
2792654012fSReza Sabdar 
2802654012fSReza Sabdar 	timeout.tv_sec = 0;
2812654012fSReza Sabdar 	timeout.tv_usec = 1000;
2822654012fSReza Sabdar 
2832654012fSReza Sabdar 	FD_ZERO(&fds);
2842654012fSReza Sabdar 	FD_SET(fd, &fds);
2852654012fSReza Sabdar 	ret = select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
2862654012fSReza Sabdar 
2872654012fSReza Sabdar 	closed = (ret == -1 && errno == EBADF);
2882654012fSReza Sabdar 
2892654012fSReza Sabdar 	return (closed);
2902654012fSReza Sabdar }
2912654012fSReza Sabdar 
2922654012fSReza Sabdar /*
2932654012fSReza Sabdar  * ndmp_check_mover_state
2942654012fSReza Sabdar  *
2952654012fSReza Sabdar  * Checks the mover connection status and sends an appropriate
2962654012fSReza Sabdar  * NDMP message to client based on that.
2972654012fSReza Sabdar  *
2982654012fSReza Sabdar  * Parameters:
2992654012fSReza Sabdar  *   ndmpd_session_t *session (input) : session pointer
3002654012fSReza Sabdar  *
3012654012fSReza Sabdar  * Returns:
3022654012fSReza Sabdar  *   void.
3032654012fSReza Sabdar  */
3042654012fSReza Sabdar void
3052654012fSReza Sabdar ndmp_check_mover_state(ndmpd_session_t *session)
3062654012fSReza Sabdar {
3072654012fSReza Sabdar 	int moverfd;
3082654012fSReza Sabdar 	/*
3092654012fSReza Sabdar 	 * NDMPV3 Spec (Three-way restore):
3102654012fSReza Sabdar 	 * Once all of the files have been recovered, NDMP DATA Server closes
3112654012fSReza Sabdar 	 * the connection to the mover on the NDMP TAPE Server. THEN
3122654012fSReza Sabdar 	 * The NDMP client should receive an NDMP_NOTIFY_MOVER_HALTED message
3132654012fSReza Sabdar 	 * with an NDMP_MOVER_CONNECT_CLOSED reason from the NDMP TAPE Server
3142654012fSReza Sabdar 	 */
3152654012fSReza Sabdar 	moverfd = session->ns_mover.md_sock;
3162654012fSReza Sabdar 	/* If connection is closed by the peer */
3172654012fSReza Sabdar 	if (moverfd >= 0 &&
3182654012fSReza Sabdar 	    session->ns_mover.md_mode == NDMP_MOVER_MODE_WRITE) {
3192654012fSReza Sabdar 		int closed, reason;
3202654012fSReza Sabdar 
3212654012fSReza Sabdar 		closed = ndmp_connection_closed(moverfd);
3222654012fSReza Sabdar 		if (closed) {
3232654012fSReza Sabdar 			/* Connection closed or internal error */
3242654012fSReza Sabdar 			if (closed > 0) {
3252654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
3262654012fSReza Sabdar 				    "ndmp mover: connection closed by peer");
3272654012fSReza Sabdar 				reason = NDMP_MOVER_HALT_CONNECT_CLOSED;
3282654012fSReza Sabdar 			} else {
3292654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
3302654012fSReza Sabdar 				    "ndmp mover: Internal error");
3312654012fSReza Sabdar 				reason = NDMP_MOVER_HALT_INTERNAL_ERROR;
3322654012fSReza Sabdar 			}
3332654012fSReza Sabdar 			ndmpd_mover_error(session, reason);
3342654012fSReza Sabdar 
3352654012fSReza Sabdar 		}
3362654012fSReza Sabdar 	}
3372654012fSReza Sabdar }
3382654012fSReza Sabdar 
3392654012fSReza Sabdar 
3402654012fSReza Sabdar /*
3412654012fSReza Sabdar  * ndmpd_select
3422654012fSReza Sabdar  *
3432654012fSReza Sabdar  * Calls select on the the set of file descriptors from the
3442654012fSReza Sabdar  * file handler list masked by the fd_class argument.
3452654012fSReza Sabdar  * Calls the file handler function for each
3462654012fSReza Sabdar  * file descriptor that is ready for I/O.
3472654012fSReza Sabdar  *
3482654012fSReza Sabdar  * Parameters:
3492654012fSReza Sabdar  *   session (input) - session pointer.
3502654012fSReza Sabdar  *   block   (input) - if TRUE, ndmpd_select waits until at least one
3512654012fSReza Sabdar  *		     file descriptor is ready for I/O. Otherwise,
3522654012fSReza Sabdar  *		     it returns immediately if no file descriptors are
3532654012fSReza Sabdar  *		     ready for I/O.
3542654012fSReza Sabdar  *   class_mask (input) - bit mask of handler classes to be examined.
3552654012fSReza Sabdar  *		     Provides for excluding some of the handlers from
3562654012fSReza Sabdar  *		     being called.
3572654012fSReza Sabdar  *
3582654012fSReza Sabdar  * Returns:
3592654012fSReza Sabdar  *  -1 - error.
3602654012fSReza Sabdar  *   0 - no handlers were called.
3612654012fSReza Sabdar  *   1 - at least one handler was called.
3622654012fSReza Sabdar  */
3632654012fSReza Sabdar int
3642654012fSReza Sabdar ndmpd_select(ndmpd_session_t *session, boolean_t block, ulong_t class_mask)
3652654012fSReza Sabdar {
3662654012fSReza Sabdar 	fd_set rfds;
3672654012fSReza Sabdar 	fd_set wfds;
3682654012fSReza Sabdar 	fd_set efds;
3692654012fSReza Sabdar 	int n;
3702654012fSReza Sabdar 	ndmpd_file_handler_t *handler;
3712654012fSReza Sabdar 	struct timeval timeout;
3722654012fSReza Sabdar 
3732654012fSReza Sabdar 	nlp_event_rv_set(session, 0);
3742654012fSReza Sabdar 
3752654012fSReza Sabdar 	if (session->ns_file_handler_list == 0)
3762654012fSReza Sabdar 		return (0);
3772654012fSReza Sabdar 
3782654012fSReza Sabdar 
3792654012fSReza Sabdar 	/*
3802654012fSReza Sabdar 	 * If select should be blocked, then we poll every ten seconds.
3812654012fSReza Sabdar 	 * The reason is in case of three-way restore we should be able
3822654012fSReza Sabdar 	 * to detect if the other end closed the connection or not.
3832654012fSReza Sabdar 	 * NDMP client(DMA) does not send any information about the connection
3842654012fSReza Sabdar 	 * that was closed in the other end.
3852654012fSReza Sabdar 	 */
3862654012fSReza Sabdar 
3872654012fSReza Sabdar 	if (block == TRUE)
3882654012fSReza Sabdar 		timeout.tv_sec = 10;
3892654012fSReza Sabdar 	else
3902654012fSReza Sabdar 		timeout.tv_sec = 0;
3912654012fSReza Sabdar 	timeout.tv_usec = 0;
3922654012fSReza Sabdar 
3932654012fSReza Sabdar 	do {
3942654012fSReza Sabdar 		/* Create the fd_sets for select. */
3952654012fSReza Sabdar 		FD_ZERO(&rfds);
3962654012fSReza Sabdar 		FD_ZERO(&wfds);
3972654012fSReza Sabdar 		FD_ZERO(&efds);
3982654012fSReza Sabdar 
3992654012fSReza Sabdar 		for (handler = session->ns_file_handler_list; handler != 0;
4002654012fSReza Sabdar 		    handler = handler->fh_next) {
4012654012fSReza Sabdar 			if ((handler->fh_class & class_mask) == 0)
4022654012fSReza Sabdar 				continue;
4032654012fSReza Sabdar 
4042654012fSReza Sabdar 			if (handler->fh_mode & NDMPD_SELECT_MODE_READ)
4052654012fSReza Sabdar 				FD_SET(handler->fh_fd, &rfds);
4062654012fSReza Sabdar 			if (handler->fh_mode & NDMPD_SELECT_MODE_WRITE)
4072654012fSReza Sabdar 				FD_SET(handler->fh_fd, &wfds);
4082654012fSReza Sabdar 			if (handler->fh_mode & NDMPD_SELECT_MODE_EXCEPTION)
4092654012fSReza Sabdar 				FD_SET(handler->fh_fd, &efds);
4102654012fSReza Sabdar 		}
4112654012fSReza Sabdar 		ndmp_check_mover_state(session);
4122654012fSReza Sabdar 		n = select(FD_SETSIZE, &rfds, &wfds, &efds, &timeout);
4132654012fSReza Sabdar 	} while (n == 0 && block == TRUE);
4142654012fSReza Sabdar 
4152654012fSReza Sabdar 	if (n < 0) {
4162654012fSReza Sabdar 		int connection_fd = ndmp_get_fd(session->ns_connection);
4172654012fSReza Sabdar 
4182654012fSReza Sabdar 		if (errno == EINTR)
4192654012fSReza Sabdar 			return (0);
4202654012fSReza Sabdar 
4212654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Select error: %m");
4222654012fSReza Sabdar 
4232654012fSReza Sabdar 		for (handler = session->ns_file_handler_list; handler != 0;
4242654012fSReza Sabdar 		    handler = handler->fh_next) {
4252654012fSReza Sabdar 			if ((handler->fh_class & class_mask) == 0)
4262654012fSReza Sabdar 				continue;
4272654012fSReza Sabdar 
4282654012fSReza Sabdar 			if (handler->fh_mode & NDMPD_SELECT_MODE_READ) {
4292654012fSReza Sabdar 				if (FD_ISSET(handler->fh_fd, &rfds) &&
4302654012fSReza Sabdar 				    connection_fd == handler->fh_fd)
4312654012fSReza Sabdar 					session->ns_eof = TRUE;
4322654012fSReza Sabdar 			}
4332654012fSReza Sabdar 			if (handler->fh_mode & NDMPD_SELECT_MODE_WRITE) {
4342654012fSReza Sabdar 				if (FD_ISSET(handler->fh_fd, &wfds) &&
4352654012fSReza Sabdar 				    connection_fd == handler->fh_fd)
4362654012fSReza Sabdar 					session->ns_eof = TRUE;
4372654012fSReza Sabdar 			}
4382654012fSReza Sabdar 			if (handler->fh_mode & NDMPD_SELECT_MODE_EXCEPTION) {
4392654012fSReza Sabdar 				if (FD_ISSET(handler->fh_fd, &efds) &&
4402654012fSReza Sabdar 				    connection_fd == handler->fh_fd)
4412654012fSReza Sabdar 					session->ns_eof = TRUE;
4422654012fSReza Sabdar 			}
4432654012fSReza Sabdar 		}
4442654012fSReza Sabdar 
4452654012fSReza Sabdar 		nlp_event_rv_set(session, -1);
4462654012fSReza Sabdar 		return (-1);
4472654012fSReza Sabdar 	}
4482654012fSReza Sabdar 	if (n == 0)
4492654012fSReza Sabdar 		return (0);
4502654012fSReza Sabdar 
4512654012fSReza Sabdar 	handler = session->ns_file_handler_list;
4522654012fSReza Sabdar 	while (handler != 0) {
4532654012fSReza Sabdar 		ulong_t mode = 0;
4542654012fSReza Sabdar 
4552654012fSReza Sabdar 		if ((handler->fh_class & class_mask) == 0) {
4562654012fSReza Sabdar 			handler = handler->fh_next;
4572654012fSReza Sabdar 			continue;
4582654012fSReza Sabdar 		}
4592654012fSReza Sabdar 		if (handler->fh_mode & NDMPD_SELECT_MODE_READ) {
4602654012fSReza Sabdar 			if (FD_ISSET(handler->fh_fd, &rfds)) {
4612654012fSReza Sabdar 				mode |= NDMPD_SELECT_MODE_READ;
4622654012fSReza Sabdar 				FD_CLR(handler->fh_fd, &rfds);
4632654012fSReza Sabdar 			}
4642654012fSReza Sabdar 		}
4652654012fSReza Sabdar 		if (handler->fh_mode & NDMPD_SELECT_MODE_WRITE) {
4662654012fSReza Sabdar 			if (FD_ISSET(handler->fh_fd, &wfds)) {
4672654012fSReza Sabdar 				mode |= NDMPD_SELECT_MODE_WRITE;
4682654012fSReza Sabdar 				FD_CLR(handler->fh_fd, &wfds);
4692654012fSReza Sabdar 			}
4702654012fSReza Sabdar 		}
4712654012fSReza Sabdar 		if (handler->fh_mode & NDMPD_SELECT_MODE_EXCEPTION) {
4722654012fSReza Sabdar 			if (FD_ISSET(handler->fh_fd, &efds)) {
4732654012fSReza Sabdar 				mode |= NDMPD_SELECT_MODE_EXCEPTION;
4742654012fSReza Sabdar 				FD_CLR(handler->fh_fd, &efds);
4752654012fSReza Sabdar 			}
4762654012fSReza Sabdar 		}
4772654012fSReza Sabdar 		if (mode) {
4782654012fSReza Sabdar 			(*handler->fh_func) (handler->fh_cookie,
4792654012fSReza Sabdar 			    handler->fh_fd, mode);
4802654012fSReza Sabdar 
4812654012fSReza Sabdar 			/*
4822654012fSReza Sabdar 			 * K.L. The list can be modified during the execution
4832654012fSReza Sabdar 			 * of handler->fh_func. Therefore, handler will start
4842654012fSReza Sabdar 			 * from the beginning of the handler list after
4852654012fSReza Sabdar 			 * each execution.
4862654012fSReza Sabdar 			 */
4872654012fSReza Sabdar 			handler = session->ns_file_handler_list;
4882654012fSReza Sabdar 
4892654012fSReza Sabdar 			/*
4902654012fSReza Sabdar 			 * Release the thread which is waiting for a request
4912654012fSReza Sabdar 			 * to be proccessed.
4922654012fSReza Sabdar 			 */
4932654012fSReza Sabdar 			nlp_event_nw(session);
4942654012fSReza Sabdar 		} else
4952654012fSReza Sabdar 			handler = handler->fh_next;
4962654012fSReza Sabdar 
4972654012fSReza Sabdar 	}
4982654012fSReza Sabdar 
4992654012fSReza Sabdar 	nlp_event_rv_set(session, 1);
5002654012fSReza Sabdar 	return (1);
5012654012fSReza Sabdar }
5022654012fSReza Sabdar 
5032654012fSReza Sabdar 
5042654012fSReza Sabdar /*
5052654012fSReza Sabdar  * ndmpd_save_env
5062654012fSReza Sabdar  *
5072654012fSReza Sabdar  * Saves a copy of the environment variable list from the data_start_backup
5082654012fSReza Sabdar  * request or data_start_recover request.
5092654012fSReza Sabdar  *
5102654012fSReza Sabdar  * Parameters:
5112654012fSReza Sabdar  *   session (input) - session pointer.
5122654012fSReza Sabdar  *   env     (input) - environment variable list to be saved.
5132654012fSReza Sabdar  *   envlen  (input) - length of variable array.
5142654012fSReza Sabdar  *
5152654012fSReza Sabdar  * Returns:
5162654012fSReza Sabdar  *   error code.
5172654012fSReza Sabdar  */
5182654012fSReza Sabdar ndmp_error
5192654012fSReza Sabdar ndmpd_save_env(ndmpd_session_t *session, ndmp_pval *env, ulong_t envlen)
5202654012fSReza Sabdar {
5212654012fSReza Sabdar 	ulong_t i;
5222654012fSReza Sabdar 	char *namebuf;
5232654012fSReza Sabdar 	char *valbuf;
5242654012fSReza Sabdar 
5252654012fSReza Sabdar 	session->ns_data.dd_env_len = 0;
5262654012fSReza Sabdar 
5272654012fSReza Sabdar 	if (envlen == 0)
5282654012fSReza Sabdar 		return (NDMP_NO_ERR);
5292654012fSReza Sabdar 
5302654012fSReza Sabdar 	session->ns_data.dd_env = ndmp_malloc(sizeof (ndmp_pval) * envlen);
5312654012fSReza Sabdar 	if (session->ns_data.dd_env == 0)
5322654012fSReza Sabdar 		return (NDMP_NO_MEM_ERR);
5332654012fSReza Sabdar 
5342654012fSReza Sabdar 	for (i = 0; i < envlen; i++) {
5352654012fSReza Sabdar 		namebuf = strdup(env[i].name);
5362654012fSReza Sabdar 		if (namebuf == 0)
5372654012fSReza Sabdar 			return (NDMP_NO_MEM_ERR);
5382654012fSReza Sabdar 
5392654012fSReza Sabdar 		valbuf = strdup(env[i].value);
5402654012fSReza Sabdar 		if (valbuf == 0) {
5412654012fSReza Sabdar 			free(namebuf);
5422654012fSReza Sabdar 			return (NDMP_NO_MEM_ERR);
5432654012fSReza Sabdar 		}
5442654012fSReza Sabdar 
5452654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "env(%s): \"%s\"",
5462654012fSReza Sabdar 		    namebuf, valbuf);
5472654012fSReza Sabdar 
5482654012fSReza Sabdar 		(void) mutex_lock(&session->ns_lock);
5492654012fSReza Sabdar 		session->ns_data.dd_env[i].name = namebuf;
5502654012fSReza Sabdar 		session->ns_data.dd_env[i].value = valbuf;
5512654012fSReza Sabdar 		session->ns_data.dd_env_len++;
5522654012fSReza Sabdar 		(void) mutex_unlock(&session->ns_lock);
5532654012fSReza Sabdar 	}
5542654012fSReza Sabdar 
5552654012fSReza Sabdar 	return (NDMP_NO_ERR);
5562654012fSReza Sabdar }
5572654012fSReza Sabdar 
5582654012fSReza Sabdar 
5592654012fSReza Sabdar /*
5602654012fSReza Sabdar  * ndmpd_free_env
5612654012fSReza Sabdar  *
5622654012fSReza Sabdar  * Free the previously saved environment variable array.
5632654012fSReza Sabdar  *
5642654012fSReza Sabdar  * Parameters:
5652654012fSReza Sabdar  *   session - NDMP session pointer.
5662654012fSReza Sabdar  *
5672654012fSReza Sabdar  * Returns:
5682654012fSReza Sabdar  *   void.
5692654012fSReza Sabdar  */
5702654012fSReza Sabdar void
5712654012fSReza Sabdar ndmpd_free_env(ndmpd_session_t *session)
5722654012fSReza Sabdar {
5732654012fSReza Sabdar 	ulong_t i;
5742654012fSReza Sabdar 	int count = session->ns_data.dd_env_len;
5752654012fSReza Sabdar 
5762654012fSReza Sabdar 	(void) mutex_lock(&session->ns_lock);
5772654012fSReza Sabdar 	session->ns_data.dd_env_len = 0;
5782654012fSReza Sabdar 	for (i = 0; i < count; i++) {
5792654012fSReza Sabdar 		free(session->ns_data.dd_env[i].name);
5802654012fSReza Sabdar 		free(session->ns_data.dd_env[i].value);
5812654012fSReza Sabdar 	}
5822654012fSReza Sabdar 
5832654012fSReza Sabdar 	free((char *)session->ns_data.dd_env);
5842654012fSReza Sabdar 	session->ns_data.dd_env = 0;
5852654012fSReza Sabdar 	(void) mutex_unlock(&session->ns_lock);
5862654012fSReza Sabdar }
5872654012fSReza Sabdar 
5882654012fSReza Sabdar 
5892654012fSReza Sabdar /*
5902654012fSReza Sabdar  * ndmpd_save_nlist_v2
5912654012fSReza Sabdar  *
5922654012fSReza Sabdar  * Save a copy of list of file names to be restored.
5932654012fSReza Sabdar  *
5942654012fSReza Sabdar  * Parameters:
5952654012fSReza Sabdar  *   nlist    (input) - name list from data_start_recover request.
5962654012fSReza Sabdar  *   nlistlen (input) - length of name list.
5972654012fSReza Sabdar  *
5982654012fSReza Sabdar  * Returns:
5992654012fSReza Sabdar  *   array of file name pointers.
6002654012fSReza Sabdar  *
6012654012fSReza Sabdar  * Notes:
6022654012fSReza Sabdar  *   free_nlist should be called to free the returned list.
6032654012fSReza Sabdar  *   A null pointer indicates the end of the list.
6042654012fSReza Sabdar  */
6052654012fSReza Sabdar ndmp_error
6062654012fSReza Sabdar ndmpd_save_nlist_v2(ndmpd_session_t *session, ndmp_name *nlist,
6072654012fSReza Sabdar     ulong_t nlistlen)
6082654012fSReza Sabdar {
6092654012fSReza Sabdar 	ulong_t i;
6102654012fSReza Sabdar 	char *namebuf;
6112654012fSReza Sabdar 	char *destbuf;
6122654012fSReza Sabdar 
6132654012fSReza Sabdar 	if (nlistlen == 0)
6142654012fSReza Sabdar 		return (NDMP_NO_ERR);
6152654012fSReza Sabdar 
6162654012fSReza Sabdar 	session->ns_data.dd_nlist_len = 0;
6172654012fSReza Sabdar 	session->ns_data.dd_nlist = ndmp_malloc(sizeof (ndmp_name)*nlistlen);
6182654012fSReza Sabdar 	if (session->ns_data.dd_nlist == 0)
6192654012fSReza Sabdar 		return (NDMP_NO_MEM_ERR);
6202654012fSReza Sabdar 
6212654012fSReza Sabdar 	for (i = 0; i < nlistlen; i++) {
6222654012fSReza Sabdar 		namebuf = ndmp_malloc(strlen(nlist[i].name) + 1);
6232654012fSReza Sabdar 		if (namebuf == 0)
6242654012fSReza Sabdar 			return (NDMP_NO_MEM_ERR);
6252654012fSReza Sabdar 
6262654012fSReza Sabdar 		destbuf = ndmp_malloc(strlen(nlist[i].dest) + 1);
6272654012fSReza Sabdar 		if (destbuf == 0) {
6282654012fSReza Sabdar 			free(namebuf);
6292654012fSReza Sabdar 			return (NDMP_NO_MEM_ERR);
6302654012fSReza Sabdar 		}
6312654012fSReza Sabdar 		(void) strlcpy(namebuf, nlist[i].name,
6322654012fSReza Sabdar 		    strlen(nlist[i].name) + 1);
6332654012fSReza Sabdar 		(void) strlcpy(destbuf, nlist[i].dest,
6342654012fSReza Sabdar 		    strlen(nlist[i].dest) + 1);
6352654012fSReza Sabdar 
6362654012fSReza Sabdar 		session->ns_data.dd_nlist[i].name = namebuf;
6372654012fSReza Sabdar 		session->ns_data.dd_nlist[i].dest = destbuf;
6382654012fSReza Sabdar 		session->ns_data.dd_nlist[i].ssid = nlist[i].ssid;
6392654012fSReza Sabdar 		session->ns_data.dd_nlist[i].fh_info = nlist[i].fh_info;
6402654012fSReza Sabdar 		session->ns_data.dd_nlist_len++;
6412654012fSReza Sabdar 	}
6422654012fSReza Sabdar 
6432654012fSReza Sabdar 	return (NDMP_NO_ERR);
6442654012fSReza Sabdar }
6452654012fSReza Sabdar 
6462654012fSReza Sabdar 
6472654012fSReza Sabdar /*
6482654012fSReza Sabdar  * ndmpd_free_nlist_v2
6492654012fSReza Sabdar  *
6502654012fSReza Sabdar  * Free a list created by ndmpd_save_nlist_v2.
6512654012fSReza Sabdar  *
6522654012fSReza Sabdar  * Parameters:
6532654012fSReza Sabdar  *   session (input) - session pointer.
6542654012fSReza Sabdar  *
6552654012fSReza Sabdar  * Returns:
6562654012fSReza Sabdar  *   void
6572654012fSReza Sabdar  */
6582654012fSReza Sabdar void
6592654012fSReza Sabdar ndmpd_free_nlist_v2(ndmpd_session_t *session)
6602654012fSReza Sabdar {
6612654012fSReza Sabdar 	ulong_t i;
6622654012fSReza Sabdar 
6632654012fSReza Sabdar 	for (i = 0; i < session->ns_data.dd_nlist_len; i++) {
6642654012fSReza Sabdar 		free(session->ns_data.dd_nlist[i].name);
6652654012fSReza Sabdar 		free(session->ns_data.dd_nlist[i].dest);
6662654012fSReza Sabdar 	}
6672654012fSReza Sabdar 
6682654012fSReza Sabdar 	if (session->ns_data.dd_nlist != NULL)
6692654012fSReza Sabdar 		free((char *)session->ns_data.dd_nlist);
6702654012fSReza Sabdar 	session->ns_data.dd_nlist = 0;
6712654012fSReza Sabdar 	session->ns_data.dd_nlist_len = 0;
6722654012fSReza Sabdar }
6732654012fSReza Sabdar 
6742654012fSReza Sabdar 
6752654012fSReza Sabdar /*
6762654012fSReza Sabdar  * ndmpd_free_nlist_v3
6772654012fSReza Sabdar  *
6782654012fSReza Sabdar  * Free a list created by ndmpd_save_nlist_v3.
6792654012fSReza Sabdar  *
6802654012fSReza Sabdar  * Parameters:
6812654012fSReza Sabdar  *   session (input) - session pointer.
6822654012fSReza Sabdar  *
6832654012fSReza Sabdar  * Returns:
6842654012fSReza Sabdar  *   void
6852654012fSReza Sabdar  */
6862654012fSReza Sabdar void
6872654012fSReza Sabdar ndmpd_free_nlist_v3(ndmpd_session_t *session)
6882654012fSReza Sabdar {
6892654012fSReza Sabdar 	ulong_t i;
6902654012fSReza Sabdar 	mem_ndmp_name_v3_t *tp; /* destination entry */
6912654012fSReza Sabdar 
6922654012fSReza Sabdar 	tp = session->ns_data.dd_nlist_v3;
6932654012fSReza Sabdar 	for (i = 0; i < session->ns_data.dd_nlist_len; tp++, i++) {
6942654012fSReza Sabdar 		NDMP_FREE(tp->nm3_opath);
6952654012fSReza Sabdar 		NDMP_FREE(tp->nm3_dpath);
6962654012fSReza Sabdar 		NDMP_FREE(tp->nm3_newnm);
6972654012fSReza Sabdar 	}
6982654012fSReza Sabdar 
6992654012fSReza Sabdar 	NDMP_FREE(session->ns_data.dd_nlist_v3);
7002654012fSReza Sabdar 	session->ns_data.dd_nlist_len = 0;
7012654012fSReza Sabdar }
7022654012fSReza Sabdar 
7032654012fSReza Sabdar 
7042654012fSReza Sabdar /*
7052654012fSReza Sabdar  * ndmpd_save_nlist_v3
7062654012fSReza Sabdar  *
7072654012fSReza Sabdar  * Save a copy of list of file names to be restored.
7082654012fSReza Sabdar  *
7092654012fSReza Sabdar  * Parameters:
7102654012fSReza Sabdar  *   nlist    (input) - name list from data_start_recover request.
7112654012fSReza Sabdar  *   nlistlen (input) - length of name list.
7122654012fSReza Sabdar  *
7132654012fSReza Sabdar  * Returns:
7142654012fSReza Sabdar  *   array of file name pointers.
7152654012fSReza Sabdar  *
7162654012fSReza Sabdar  * Notes:
7172654012fSReza Sabdar  *   free_nlist should be called to free the returned list.
7182654012fSReza Sabdar  *   A null pointer indicates the end of the list.
7192654012fSReza Sabdar  */
7202654012fSReza Sabdar ndmp_error
7212654012fSReza Sabdar ndmpd_save_nlist_v3(ndmpd_session_t *session, ndmp_name_v3 *nlist,
7222654012fSReza Sabdar     ulong_t nlistlen)
7232654012fSReza Sabdar {
7242654012fSReza Sabdar 	ulong_t i;
7252654012fSReza Sabdar 	ndmp_error rv;
7262654012fSReza Sabdar 	ndmp_name_v3 *sp; /* source entry */
7272654012fSReza Sabdar 	mem_ndmp_name_v3_t *tp; /* destination entry */
7282654012fSReza Sabdar 
7292654012fSReza Sabdar 	if (nlistlen == 0)
7302654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
7312654012fSReza Sabdar 
7322654012fSReza Sabdar 	session->ns_data.dd_nlist_len = 0;
7332654012fSReza Sabdar 	tp = session->ns_data.dd_nlist_v3 =
7342654012fSReza Sabdar 	    ndmp_malloc(sizeof (mem_ndmp_name_v3_t) * nlistlen);
7352654012fSReza Sabdar 	if (session->ns_data.dd_nlist_v3 == 0)
7362654012fSReza Sabdar 		return (NDMP_NO_MEM_ERR);
7372654012fSReza Sabdar 
7382654012fSReza Sabdar 	rv = NDMP_NO_ERR;
7392654012fSReza Sabdar 	sp = nlist;
7402654012fSReza Sabdar 	for (i = 0; i < nlistlen; tp++, sp++, i++) {
7412654012fSReza Sabdar 		tp->nm3_opath = strdup(sp->original_path);
7422654012fSReza Sabdar 		if (!tp->nm3_opath) {
7432654012fSReza Sabdar 			rv = NDMP_NO_MEM_ERR;
7442654012fSReza Sabdar 			break;
7452654012fSReza Sabdar 		}
7462654012fSReza Sabdar 		if (!*sp->destination_dir) {
7472654012fSReza Sabdar 			tp->nm3_dpath = NULL;
7482654012fSReza Sabdar 			/* In V4 destination dir cannot be NULL */
7492654012fSReza Sabdar 			if (session->ns_protocol_version == NDMPV4) {
7502654012fSReza Sabdar 				rv = NDMP_ILLEGAL_ARGS_ERR;
7512654012fSReza Sabdar 				break;
7522654012fSReza Sabdar 			}
7532654012fSReza Sabdar 		} else if (!(tp->nm3_dpath = strdup(sp->destination_dir))) {
7542654012fSReza Sabdar 			rv = NDMP_NO_MEM_ERR;
7552654012fSReza Sabdar 			break;
7562654012fSReza Sabdar 		}
7572654012fSReza Sabdar 		if (!*sp->new_name)
7582654012fSReza Sabdar 			tp->nm3_newnm = NULL;
7592654012fSReza Sabdar 		else if (!(tp->nm3_newnm = strdup(sp->new_name))) {
7602654012fSReza Sabdar 			rv = NDMP_NO_MEM_ERR;
7612654012fSReza Sabdar 			break;
7622654012fSReza Sabdar 		}
7632654012fSReza Sabdar 
7642654012fSReza Sabdar 		tp->nm3_node = quad_to_long_long(sp->node);
7652654012fSReza Sabdar 		tp->nm3_fh_info = quad_to_long_long(sp->fh_info);
7662654012fSReza Sabdar 		tp->nm3_err = NDMP_NO_ERR;
7672654012fSReza Sabdar 		session->ns_data.dd_nlist_len++;
7682654012fSReza Sabdar 
7692654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "orig \"%s\"", tp->nm3_opath);
7702654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "dest \"%s\"", NDMP_SVAL(tp->nm3_dpath));
7712654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "name \"%s\"", NDMP_SVAL(tp->nm3_newnm));
7722654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "node %lld", tp->nm3_node);
7732654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "fh_info %lld", tp->nm3_fh_info);
7742654012fSReza Sabdar 	}
7752654012fSReza Sabdar 
7762654012fSReza Sabdar 	if (rv != NDMP_NO_ERR)
7772654012fSReza Sabdar 		ndmpd_free_nlist_v3(session);
7782654012fSReza Sabdar 
7792654012fSReza Sabdar 	return (rv);
7802654012fSReza Sabdar }
7812654012fSReza Sabdar 
7822654012fSReza Sabdar 
7832654012fSReza Sabdar /*
7842654012fSReza Sabdar  * ndmpd_free_nlist
7852654012fSReza Sabdar  *
7862654012fSReza Sabdar  * Free the recovery list based on the version
7872654012fSReza Sabdar  *
7882654012fSReza Sabdar  * Parameters:
7892654012fSReza Sabdar  *   session (input) - session pointer.
7902654012fSReza Sabdar  *
7912654012fSReza Sabdar  * Returns:
7922654012fSReza Sabdar  *   void
7932654012fSReza Sabdar  */
7942654012fSReza Sabdar void
7952654012fSReza Sabdar ndmpd_free_nlist(ndmpd_session_t *session)
7962654012fSReza Sabdar {
7972654012fSReza Sabdar 	switch (session->ns_protocol_version) {
7982654012fSReza Sabdar 	case 1:
7992654012fSReza Sabdar 	case 2:
8002654012fSReza Sabdar 		ndmpd_free_nlist_v2(session);
8012654012fSReza Sabdar 		break;
8022654012fSReza Sabdar 	case 3:
8032654012fSReza Sabdar 	case 4:
8042654012fSReza Sabdar 		ndmpd_free_nlist_v3(session);
8052654012fSReza Sabdar 		break;
8062654012fSReza Sabdar 
8072654012fSReza Sabdar 	default:
8082654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Unknown version %d",
8092654012fSReza Sabdar 		    session->ns_protocol_version);
8102654012fSReza Sabdar 	}
8112654012fSReza Sabdar }
8122654012fSReza Sabdar 
8132654012fSReza Sabdar 
8142654012fSReza Sabdar /*
8152654012fSReza Sabdar  * fh_cmpv3
8162654012fSReza Sabdar  *
8172654012fSReza Sabdar  * Comparison function used in sorting the Nlist based on their
8182654012fSReza Sabdar  * file history info (offset of the entry on the tape)
8192654012fSReza Sabdar  *
8202654012fSReza Sabdar  * Parameters:
8212654012fSReza Sabdar  *   p (input) - pointer to P
8222654012fSReza Sabdar  *   q (input) - pointer to Q
8232654012fSReza Sabdar  *
8242654012fSReza Sabdar  * Returns:
8252654012fSReza Sabdar  *  -1: P < Q
8262654012fSReza Sabdar  *   0: P = Q
8272654012fSReza Sabdar  *   1: P > Q
8282654012fSReza Sabdar  */
8292654012fSReza Sabdar static int
8302654012fSReza Sabdar fh_cmpv3(const void *p,
8312654012fSReza Sabdar 		const void *q)
8322654012fSReza Sabdar {
8332654012fSReza Sabdar #define	FH_INFOV3(p)	(((mem_ndmp_name_v3_t *)p)->nm3_fh_info)
8342654012fSReza Sabdar 
8352654012fSReza Sabdar 	if (FH_INFOV3(p) < FH_INFOV3(q))
8362654012fSReza Sabdar 		return (-1);
8372654012fSReza Sabdar 	else if (FH_INFOV3(p) == FH_INFOV3(q))
8382654012fSReza Sabdar 		return (0);
8392654012fSReza Sabdar 	else
8402654012fSReza Sabdar 		return (1);
8412654012fSReza Sabdar 
8422654012fSReza Sabdar #undef FH_INFOV3
8432654012fSReza Sabdar }
8442654012fSReza Sabdar 
8452654012fSReza Sabdar 
8462654012fSReza Sabdar /*
8472654012fSReza Sabdar  * ndmp_sort_nlist_v3
8482654012fSReza Sabdar  *
8492654012fSReza Sabdar  * Sort the recovery list based on their offset on the tape
8502654012fSReza Sabdar  *
8512654012fSReza Sabdar  * Parameters:
8522654012fSReza Sabdar  *   session (input) - session pointer.
8532654012fSReza Sabdar  *
8542654012fSReza Sabdar  * Returns:
8552654012fSReza Sabdar  *   void
8562654012fSReza Sabdar  */
8572654012fSReza Sabdar void
8582654012fSReza Sabdar ndmp_sort_nlist_v3(ndmpd_session_t *session)
8592654012fSReza Sabdar {
8602654012fSReza Sabdar 	if (!session || session->ns_data.dd_nlist_len == 0 ||
8612654012fSReza Sabdar 	    !session->ns_data.dd_nlist_v3)
8622654012fSReza Sabdar 		return;
8632654012fSReza Sabdar 
8642654012fSReza Sabdar 	(void) qsort(session->ns_data.dd_nlist_v3,
8652654012fSReza Sabdar 	    session->ns_data.dd_nlist_len,
8662654012fSReza Sabdar 	    sizeof (mem_ndmp_name_v3_t), fh_cmpv3);
8672654012fSReza Sabdar }
8682654012fSReza Sabdar 
8692654012fSReza Sabdar 
8702654012fSReza Sabdar /*
8712654012fSReza Sabdar  * ndmp_send_reply
8722654012fSReza Sabdar  *
8732654012fSReza Sabdar  * Send the reply, check for error and print the msg if any error
8742654012fSReza Sabdar  * occured when sending the reply.
8752654012fSReza Sabdar  *
8762654012fSReza Sabdar  *   Parameters:
8772654012fSReza Sabdar  *     connection (input) - connection pointer.
8782654012fSReza Sabdar  *
8792654012fSReza Sabdar  *   Return:
8802654012fSReza Sabdar  *     void
8812654012fSReza Sabdar  */
8822654012fSReza Sabdar void
8832654012fSReza Sabdar ndmp_send_reply(ndmp_connection_t *connection, void *reply, char *msg)
8842654012fSReza Sabdar {
8852654012fSReza Sabdar 	if (ndmp_send_response(connection, NDMP_NO_ERR, reply) < 0)
8862654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "%s", msg);
8872654012fSReza Sabdar }
8882654012fSReza Sabdar 
8892654012fSReza Sabdar 
8902654012fSReza Sabdar /*
8912654012fSReza Sabdar  * ndmp_mtioctl
8922654012fSReza Sabdar  *
8932654012fSReza Sabdar  * Performs numerous filemark operations.
8942654012fSReza Sabdar  *
8952654012fSReza Sabdar  * Parameters:
8962654012fSReza Sabdar  * 	fd - file descriptor of the device
8972654012fSReza Sabdar  *	cmd - filemark or record command
8982654012fSReza Sabdar  * 	count - the number of operations to be performed
8992654012fSReza Sabdar  */
9002654012fSReza Sabdar int
9012654012fSReza Sabdar ndmp_mtioctl(int fd, int cmd, int count)
9022654012fSReza Sabdar {
9032654012fSReza Sabdar 	struct mtop mp;
9042654012fSReza Sabdar 
9052654012fSReza Sabdar 	mp.mt_op = cmd;
9062654012fSReza Sabdar 	mp.mt_count = count;
9072654012fSReza Sabdar 	if (ioctl(fd, MTIOCTOP, &mp) < 0) {
9082654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Failed to send command to tape: %m.");
9092654012fSReza Sabdar 		return (-1);
9102654012fSReza Sabdar 	}
9112654012fSReza Sabdar 
9122654012fSReza Sabdar 	return (0);
9132654012fSReza Sabdar }
9142654012fSReza Sabdar 
9152654012fSReza Sabdar 
9162654012fSReza Sabdar /*
9172654012fSReza Sabdar  * quad_to_long_long
9182654012fSReza Sabdar  *
9192654012fSReza Sabdar  * Convert type quad to longlong_t
9202654012fSReza Sabdar  */
9212654012fSReza Sabdar u_longlong_t
9222654012fSReza Sabdar quad_to_long_long(ndmp_u_quad q)
9232654012fSReza Sabdar {
9242654012fSReza Sabdar 	u_longlong_t ull;
9252654012fSReza Sabdar 
9262654012fSReza Sabdar 	ull = ((u_longlong_t)q.high << 32) + q.low;
9272654012fSReza Sabdar 	return (ull);
9282654012fSReza Sabdar }
9292654012fSReza Sabdar 
9302654012fSReza Sabdar 
9312654012fSReza Sabdar /*
9322654012fSReza Sabdar  * long_long_to_quad
9332654012fSReza Sabdar  *
9342654012fSReza Sabdar  * Convert long long to quad type
9352654012fSReza Sabdar  */
9362654012fSReza Sabdar ndmp_u_quad
9372654012fSReza Sabdar long_long_to_quad(u_longlong_t ull)
9382654012fSReza Sabdar {
9392654012fSReza Sabdar 	ndmp_u_quad q;
9402654012fSReza Sabdar 
9412654012fSReza Sabdar 	q.high = (ulong_t)(ull >> 32);
9422654012fSReza Sabdar 	q.low = (ulong_t)ull;
9432654012fSReza Sabdar 	return (q);
9442654012fSReza Sabdar }
9452654012fSReza Sabdar 
9462654012fSReza Sabdar 
9472654012fSReza Sabdar /*
9482654012fSReza Sabdar  * ndmp_set_socket_nodelay
9492654012fSReza Sabdar  *
9502654012fSReza Sabdar  * Set the TCP socket option to nodelay mode
9512654012fSReza Sabdar  */
9522654012fSReza Sabdar void
9532654012fSReza Sabdar ndmp_set_socket_nodelay(int sock)
9542654012fSReza Sabdar {
9552654012fSReza Sabdar 	int flag = 1;
9562654012fSReza Sabdar 
9572654012fSReza Sabdar 	(void) setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof (flag));
9582654012fSReza Sabdar }
9592654012fSReza Sabdar 
9602654012fSReza Sabdar 
9612654012fSReza Sabdar /*
9622654012fSReza Sabdar  * ndmp_set_socket_snd_buf
9632654012fSReza Sabdar  *
9642654012fSReza Sabdar  * Set the socket send buffer size
9652654012fSReza Sabdar  */
9662654012fSReza Sabdar void
9672654012fSReza Sabdar ndmp_set_socket_snd_buf(int sock, int size)
9682654012fSReza Sabdar {
9692654012fSReza Sabdar 	if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) < 0)
9702654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "SO_SNDBUF failed errno=%d", errno);
9712654012fSReza Sabdar }
9722654012fSReza Sabdar 
9732654012fSReza Sabdar 
9742654012fSReza Sabdar /*
9752654012fSReza Sabdar  * ndmp_set_socket_rcv_buf
9762654012fSReza Sabdar  *
9772654012fSReza Sabdar  * Set the socket receive buffer size
9782654012fSReza Sabdar  */
9792654012fSReza Sabdar void
9802654012fSReza Sabdar ndmp_set_socket_rcv_buf(int sock, int size)
9812654012fSReza Sabdar {
9822654012fSReza Sabdar 	if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size)) < 0)
9832654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "SO_RCVBUF failed errno=%d", errno);
9842654012fSReza Sabdar }
9852654012fSReza Sabdar 
9862654012fSReza Sabdar /*
9872654012fSReza Sabdar  * ndmp_get_max_tok_seq
9882654012fSReza Sabdar  *
9892654012fSReza Sabdar  * Get the maximum permitted token sequence for token-based
9902654012fSReza Sabdar  * backups.
9912654012fSReza Sabdar  *
9922654012fSReza Sabdar  * Parameters:
9932654012fSReza Sabdar  *   void
9942654012fSReza Sabdar  *
9952654012fSReza Sabdar  * Returns:
9962654012fSReza Sabdar  *   ndmp_max_tok_seq
9972654012fSReza Sabdar  */
9982654012fSReza Sabdar int
9992654012fSReza Sabdar ndmp_get_max_tok_seq(void)
10002654012fSReza Sabdar {
10012654012fSReza Sabdar 	return (ndmp_max_tok_seq);
10022654012fSReza Sabdar }
10032654012fSReza Sabdar 
10042654012fSReza Sabdar /*
10052654012fSReza Sabdar  * ndmp_buffer_get_size
10062654012fSReza Sabdar  *
10072654012fSReza Sabdar  * Return the NDMP transfer buffer size
10082654012fSReza Sabdar  *
10092654012fSReza Sabdar  * Parameters:
10102654012fSReza Sabdar  *   session (input) - session pointer.
10112654012fSReza Sabdar  *
10122654012fSReza Sabdar  * Returns:
10132654012fSReza Sabdar  *   buffer size
10142654012fSReza Sabdar  */
10152654012fSReza Sabdar long
10162654012fSReza Sabdar ndmp_buffer_get_size(ndmpd_session_t *session)
10172654012fSReza Sabdar {
10182654012fSReza Sabdar 	long xfer_size;
10192654012fSReza Sabdar 
10202654012fSReza Sabdar 	if (session == NULL)
10212654012fSReza Sabdar 		return (0);
10222654012fSReza Sabdar 
10232654012fSReza Sabdar 	if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
10242654012fSReza Sabdar 		xfer_size = atoi(ndmpd_get_prop_default(NDMP_MOVER_RECSIZE,
10252654012fSReza Sabdar 		    "60"));
10262654012fSReza Sabdar 		if (xfer_size > 0)
10272654012fSReza Sabdar 			xfer_size *= KILOBYTE;
10282654012fSReza Sabdar 		else
10292654012fSReza Sabdar 			xfer_size = REMOTE_RECORD_SIZE;
10302654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Remote operation: %d", xfer_size);
10312654012fSReza Sabdar 	} else {
10322654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
10332654012fSReza Sabdar 		    "Local operation: %lu", session->ns_mover.md_record_size);
10342654012fSReza Sabdar 		if ((xfer_size = session->ns_mover.md_record_size) == 0)
10352654012fSReza Sabdar 			xfer_size = MAX_RECORD_SIZE;
10362654012fSReza Sabdar 	}
10372654012fSReza Sabdar 
10382654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "xfer_size: %d", xfer_size);
10392654012fSReza Sabdar 	return (xfer_size);
10402654012fSReza Sabdar }
10412654012fSReza Sabdar 
10422654012fSReza Sabdar 
10432654012fSReza Sabdar /*
10442654012fSReza Sabdar  * ndmp_lbr_init
10452654012fSReza Sabdar  *
10462654012fSReza Sabdar  * Initialize the LBR/NDMP backup parameters
10472654012fSReza Sabdar  *
10482654012fSReza Sabdar  * Parameters:
10492654012fSReza Sabdar  *   session (input) - session pointer.
10502654012fSReza Sabdar  *
10512654012fSReza Sabdar  * Returns:
10522654012fSReza Sabdar  *   0: on success
10532654012fSReza Sabdar  *  -1: otherwise
10542654012fSReza Sabdar  */
10552654012fSReza Sabdar int
10562654012fSReza Sabdar ndmp_lbr_init(ndmpd_session_t *session)
10572654012fSReza Sabdar {
10582654012fSReza Sabdar 	if (session->ns_ndmp_lbr_params != NULL) {
10592654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "ndmp_lbr_params already allocated.");
10602654012fSReza Sabdar 		return (0);
10612654012fSReza Sabdar 	}
10622654012fSReza Sabdar 
10632654012fSReza Sabdar 	session->ns_ndmp_lbr_params = ndmp_malloc(sizeof (ndmp_lbr_params_t));
10642654012fSReza Sabdar 	if (session->ns_ndmp_lbr_params == NULL)
10652654012fSReza Sabdar 		return (-1);
10662654012fSReza Sabdar 
10672654012fSReza Sabdar 	session->ns_ndmp_lbr_params->nlp_bkmap = -1;
10682654012fSReza Sabdar 	session->ns_ndmp_lbr_params->nlp_session = session;
10692654012fSReza Sabdar 	(void) cond_init(&session->ns_ndmp_lbr_params->nlp_cv, 0, NULL);
10702654012fSReza Sabdar 	(void) mutex_init(&session->ns_lock, 0, NULL);
10712654012fSReza Sabdar 	session->ns_nref = 0;
10722654012fSReza Sabdar 	return (0);
10732654012fSReza Sabdar }
10742654012fSReza Sabdar 
10752654012fSReza Sabdar 
10762654012fSReza Sabdar /*
10772654012fSReza Sabdar  * ndmp_lbr_cleanup
10782654012fSReza Sabdar  *
10792654012fSReza Sabdar  * Deallocate and cleanup all NDMP/LBR parameters
10802654012fSReza Sabdar  *
10812654012fSReza Sabdar  * Parameters:
10822654012fSReza Sabdar  *   session (input) - session pointer.
10832654012fSReza Sabdar  *
10842654012fSReza Sabdar  * Returns:
10852654012fSReza Sabdar  *   0: on success
10862654012fSReza Sabdar  *  -1: otherwise
10872654012fSReza Sabdar  */
10882654012fSReza Sabdar void
10892654012fSReza Sabdar ndmp_lbr_cleanup(ndmpd_session_t *session)
10902654012fSReza Sabdar {
10912654012fSReza Sabdar 	/*
10922654012fSReza Sabdar 	 * If in 3-way restore, the connection close is detected after
10932654012fSReza Sabdar 	 * check in tape_read(), the reader thread of mover may wait forever
10942654012fSReza Sabdar 	 * for the tape to be changed.  Force the reader thread to exit.
10952654012fSReza Sabdar 	 */
10962654012fSReza Sabdar 	nlp_event_rv_set(session, -2);
10972654012fSReza Sabdar 	nlp_event_nw(session);
10982654012fSReza Sabdar 
10992654012fSReza Sabdar 	ndmpd_abort_marking_v2(session);
11002654012fSReza Sabdar 	ndmp_stop_buffer_worker(session);
11012654012fSReza Sabdar 	ndmp_waitfor_op(session);
11022654012fSReza Sabdar 	ndmp_free_reader_writer_ipc(session);
11032654012fSReza Sabdar 	if (session->ns_ndmp_lbr_params) {
11042654012fSReza Sabdar 		if (session->ns_ndmp_lbr_params->nlp_bkmap != -1)
11052654012fSReza Sabdar 			(void) dbm_free(session->ns_ndmp_lbr_params->nlp_bkmap);
11062654012fSReza Sabdar 		tlm_release_list(session->ns_ndmp_lbr_params->nlp_exl);
11072654012fSReza Sabdar 		tlm_release_list(session->ns_ndmp_lbr_params->nlp_inc);
11082654012fSReza Sabdar 		(void) cond_destroy(&session->ns_ndmp_lbr_params->nlp_cv);
11092654012fSReza Sabdar 	}
11102654012fSReza Sabdar 
11112654012fSReza Sabdar 	NDMP_FREE(session->ns_ndmp_lbr_params);
11122654012fSReza Sabdar }
11132654012fSReza Sabdar 
11142654012fSReza Sabdar 
11152654012fSReza Sabdar /*
11162654012fSReza Sabdar  * nlp_ref_nw
11172654012fSReza Sabdar  *
11182654012fSReza Sabdar  * Increase the references to the NDMP/LBR parameter to prevent
11192654012fSReza Sabdar  * unwanted release
11202654012fSReza Sabdar  *
11212654012fSReza Sabdar  * Parameters:
11222654012fSReza Sabdar  *   session (input) - session pointer.
11232654012fSReza Sabdar  *
11242654012fSReza Sabdar  * Returns:
11252654012fSReza Sabdar  *   void
11262654012fSReza Sabdar  */
11272654012fSReza Sabdar void
11282654012fSReza Sabdar nlp_ref_nw(ndmpd_session_t *session)
11292654012fSReza Sabdar {
11302654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
11312654012fSReza Sabdar 
11322654012fSReza Sabdar 	(void) mutex_lock(&nlp_mtx);
11332654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) != NULL) {
11342654012fSReza Sabdar 		nlp->nlp_nw++;
11352654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nw: %d", nlp->nlp_nw);
11362654012fSReza Sabdar 	} else
11372654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
11382654012fSReza Sabdar 	(void) mutex_unlock(&nlp_mtx);
11392654012fSReza Sabdar }
11402654012fSReza Sabdar 
11412654012fSReza Sabdar 
11422654012fSReza Sabdar /*
11432654012fSReza Sabdar  * nlp_unref_nw
11442654012fSReza Sabdar  *
11452654012fSReza Sabdar  * Decrease the references to the NDMP/LBR parameter before
11462654012fSReza Sabdar  * release
11472654012fSReza Sabdar  *
11482654012fSReza Sabdar  * Parameters:
11492654012fSReza Sabdar  *   session (input) - session pointer.
11502654012fSReza Sabdar  *
11512654012fSReza Sabdar  * Returns:
11522654012fSReza Sabdar  *   void
11532654012fSReza Sabdar  */
11542654012fSReza Sabdar void
11552654012fSReza Sabdar nlp_unref_nw(ndmpd_session_t *session)
11562654012fSReza Sabdar {
11572654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
11582654012fSReza Sabdar 
11592654012fSReza Sabdar 	(void) mutex_lock(&nlp_mtx);
11602654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) != NULL) {
11612654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nw: %d", nlp->nlp_nw);
11622654012fSReza Sabdar 		if (nlp->nlp_nw > 0)
11632654012fSReza Sabdar 			nlp->nlp_nw--;
11642654012fSReza Sabdar 	} else
11652654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
11662654012fSReza Sabdar 	(void) mutex_unlock(&nlp_mtx);
11672654012fSReza Sabdar }
11682654012fSReza Sabdar 
11692654012fSReza Sabdar 
11702654012fSReza Sabdar /*
11712654012fSReza Sabdar  * nlp_wait_nw
11722654012fSReza Sabdar  *
11732654012fSReza Sabdar  * Wait for a NDMP/LBR parameter to get available
11742654012fSReza Sabdar  *
11752654012fSReza Sabdar  * Parameters:
11762654012fSReza Sabdar  *   session (input) - session pointer.
11772654012fSReza Sabdar  *
11782654012fSReza Sabdar  * Returns:
11792654012fSReza Sabdar  *   void
11802654012fSReza Sabdar  */
11812654012fSReza Sabdar void
11822654012fSReza Sabdar nlp_wait_nw(ndmpd_session_t *session)
11832654012fSReza Sabdar {
11842654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
11852654012fSReza Sabdar 
11862654012fSReza Sabdar 	(void) mutex_lock(&nlp_mtx);
11872654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) != NULL) {
11882654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nw: %d", nlp->nlp_nw);
11892654012fSReza Sabdar 		if (nlp->nlp_nw > 0) {
11902654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "Waiting");
11912654012fSReza Sabdar 			while ((nlp->nlp_flag & NLP_READY) == 0)
11922654012fSReza Sabdar 				(void) cond_wait(&nlp->nlp_cv, &nlp_mtx);
11932654012fSReza Sabdar 		}
11942654012fSReza Sabdar 	} else
11952654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
11962654012fSReza Sabdar 	(void) mutex_unlock(&nlp_mtx);
11972654012fSReza Sabdar }
11982654012fSReza Sabdar 
11992654012fSReza Sabdar 
12002654012fSReza Sabdar /*
12012654012fSReza Sabdar  * nlp_event_nw
12022654012fSReza Sabdar  *
12032654012fSReza Sabdar  * Signal that a NDMP/LBR parameter is available to wake up the
12042654012fSReza Sabdar  * threads waiting on that
12052654012fSReza Sabdar  *
12062654012fSReza Sabdar  * Parameters:
12072654012fSReza Sabdar  *   session (input) - session pointer.
12082654012fSReza Sabdar  *
12092654012fSReza Sabdar  * Returns:
12102654012fSReza Sabdar  *   void
12112654012fSReza Sabdar  */
12122654012fSReza Sabdar void
12132654012fSReza Sabdar nlp_event_nw(ndmpd_session_t *session)
12142654012fSReza Sabdar {
12152654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
12162654012fSReza Sabdar 
12172654012fSReza Sabdar 	(void) mutex_lock(&nlp_mtx);
12182654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) != NULL) {
12192654012fSReza Sabdar 		if (nlp->nlp_nw > 0) {
12202654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "nw: %d", nlp->nlp_nw);
12212654012fSReza Sabdar 			nlp->nlp_flag |= NLP_READY;
12222654012fSReza Sabdar 			(void) cond_signal(&nlp->nlp_cv);
12232654012fSReza Sabdar 		}
12242654012fSReza Sabdar 	} else
12252654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
12262654012fSReza Sabdar 	(void) mutex_unlock(&nlp_mtx);
12272654012fSReza Sabdar }
12282654012fSReza Sabdar 
12292654012fSReza Sabdar 
12302654012fSReza Sabdar /*
12312654012fSReza Sabdar  * nlp_event_rv_get
12322654012fSReza Sabdar  *
12332654012fSReza Sabdar  * Get the return value for each NLP
12342654012fSReza Sabdar  *
12352654012fSReza Sabdar  * Parameters:
12362654012fSReza Sabdar  *   session (input) - session pointer.
12372654012fSReza Sabdar  *
12382654012fSReza Sabdar  * Returns:
12392654012fSReza Sabdar  *   return value
12402654012fSReza Sabdar  */
12412654012fSReza Sabdar int
12422654012fSReza Sabdar nlp_event_rv_get(ndmpd_session_t *session)
12432654012fSReza Sabdar {
12442654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
12452654012fSReza Sabdar 
12462654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
12472654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
12482654012fSReza Sabdar 		return (0);
12492654012fSReza Sabdar 	}
12502654012fSReza Sabdar 
12512654012fSReza Sabdar 	return (nlp->nlp_rv);
12522654012fSReza Sabdar }
12532654012fSReza Sabdar 
12542654012fSReza Sabdar 
12552654012fSReza Sabdar /*
12562654012fSReza Sabdar  * nlp_event_rv_set
12572654012fSReza Sabdar  *
12582654012fSReza Sabdar  * Set the return value for an NLP
12592654012fSReza Sabdar  *
12602654012fSReza Sabdar  * Parameters:
12612654012fSReza Sabdar  *   session (input) - session pointer.
12622654012fSReza Sabdar  *   rv (input) - return value
12632654012fSReza Sabdar  *
12642654012fSReza Sabdar  * Returns:
12652654012fSReza Sabdar  *   void
12662654012fSReza Sabdar  */
12672654012fSReza Sabdar void
12682654012fSReza Sabdar nlp_event_rv_set(ndmpd_session_t *session,
12692654012fSReza Sabdar     int rv)
12702654012fSReza Sabdar {
12712654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
12722654012fSReza Sabdar 
12732654012fSReza Sabdar 	(void) mutex_lock(&nlp_mtx);
12742654012fSReza Sabdar 	if (rv != 0)
12752654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "rv: %d", rv);
12762654012fSReza Sabdar 
12772654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) != NULL)
12782654012fSReza Sabdar 		nlp->nlp_rv = rv;
12792654012fSReza Sabdar 	else
12802654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
12812654012fSReza Sabdar 	(void) mutex_unlock(&nlp_mtx);
12822654012fSReza Sabdar }
12832654012fSReza Sabdar 
12842654012fSReza Sabdar /*
12852654012fSReza Sabdar  * is_buffer_erroneous
12862654012fSReza Sabdar  *
12872654012fSReza Sabdar  * Run a sanity check on the buffer
12882654012fSReza Sabdar  *
12892654012fSReza Sabdar  * returns:
12902654012fSReza Sabdar  *   TRUE: if the buffer seems to have error
12912654012fSReza Sabdar  *   FALSE: if the buffer is full and has valid data.
12922654012fSReza Sabdar  */
12932654012fSReza Sabdar boolean_t
12942654012fSReza Sabdar is_buffer_erroneous(tlm_buffer_t *buf)
12952654012fSReza Sabdar {
12962654012fSReza Sabdar 	boolean_t rv;
12972654012fSReza Sabdar 
12982654012fSReza Sabdar 	rv = (buf == NULL || buf->tb_eot || buf->tb_eof ||
12992654012fSReza Sabdar 	    buf->tb_errno != 0);
13002654012fSReza Sabdar 	if (rv) {
13012654012fSReza Sabdar 		if (buf == NULL) {
13022654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "buf == NULL");
13032654012fSReza Sabdar 		} else {
13042654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "eot: %u, eof: %u, errno: %d",
13052654012fSReza Sabdar 			    buf->tb_eot, buf->tb_eof, buf->tb_errno);
13062654012fSReza Sabdar 		}
13072654012fSReza Sabdar 	}
13082654012fSReza Sabdar 
13092654012fSReza Sabdar 	return (rv);
13102654012fSReza Sabdar }
13112654012fSReza Sabdar 
13122654012fSReza Sabdar /*
13132654012fSReza Sabdar  * ndmp_execute_cdb
13142654012fSReza Sabdar  *
13152654012fSReza Sabdar  * Main SCSI CDB execution program, this is used by message handler
13162654012fSReza Sabdar  * for the NDMP tape/SCSI execute CDB requests. This function uses
13172654012fSReza Sabdar  * USCSI interface to run the CDB command and sets all the CDB parameters
13182654012fSReza Sabdar  * in the SCSI query before calling the USCSI ioctl. The result of the
13192654012fSReza Sabdar  * CDB is returned in two places:
13202654012fSReza Sabdar  *    cmd.uscsi_status		The status of CDB execution
13212654012fSReza Sabdar  *    cmd.uscsi_rqstatus	The status of sense requests
13222654012fSReza Sabdar  *    reply.error		The general errno (ioctl)
13232654012fSReza Sabdar  *
13242654012fSReza Sabdar  * Parameters:
13252654012fSReza Sabdar  *   session (input) - session pointer
13262654012fSReza Sabdar  *   adapter_name (input) - name of SCSI adapter
13272654012fSReza Sabdar  *   sid (input) - SCSI target ID
13282654012fSReza Sabdar  *   lun (input) - LUN number
13292654012fSReza Sabdar  *   request (input) - NDMP client CDB request
13302654012fSReza Sabdar  *
13312654012fSReza Sabdar  * Returns:
13322654012fSReza Sabdar  *   void
13332654012fSReza Sabdar  */
13342654012fSReza Sabdar /*ARGSUSED*/
13352654012fSReza Sabdar void
13362654012fSReza Sabdar ndmp_execute_cdb(ndmpd_session_t *session, char *adapter_name, int sid, int lun,
13372654012fSReza Sabdar     ndmp_execute_cdb_request *request)
13382654012fSReza Sabdar {
13392654012fSReza Sabdar 	ndmp_execute_cdb_reply reply;
13402654012fSReza Sabdar 	struct uscsi_cmd cmd;
13412654012fSReza Sabdar 	int fd;
13422654012fSReza Sabdar 	struct open_list *olp;
13432654012fSReza Sabdar 	char rq_buf[255];
13442654012fSReza Sabdar 
13452654012fSReza Sabdar 	(void) memset((void *)&cmd, 0, sizeof (cmd));
13462654012fSReza Sabdar 	(void) memset((void *)&reply, 0, sizeof (reply));
13472654012fSReza Sabdar 	(void) memset((void *)rq_buf, 0, sizeof (rq_buf));
13482654012fSReza Sabdar 
13492654012fSReza Sabdar 	if (request->flags == NDMP_SCSI_DATA_IN) {
1350b6b15642SReza Sabdar 		cmd.uscsi_flags = USCSI_READ | USCSI_RQENABLE;
13512654012fSReza Sabdar 		if ((cmd.uscsi_bufaddr =
13522654012fSReza Sabdar 		    ndmp_malloc(request->datain_len)) == 0) {
13532654012fSReza Sabdar 			reply.error = NDMP_NO_MEM_ERR;
13542654012fSReza Sabdar 			if (ndmp_send_response(session->ns_connection,
13552654012fSReza Sabdar 			    NDMP_NO_ERR, (void *)&reply) < 0)
13562654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG, "error sending"
13572654012fSReza Sabdar 				    " scsi_execute_cdb reply.");
13582654012fSReza Sabdar 			return;
13592654012fSReza Sabdar 		}
13602654012fSReza Sabdar 
13612654012fSReza Sabdar 		cmd.uscsi_buflen = request->datain_len;
13622654012fSReza Sabdar 	} else if (request->flags == NDMP_SCSI_DATA_OUT) {
1363*65451a03SReza Sabdar 		cmd.uscsi_flags = USCSI_WRITE | USCSI_RQENABLE;
13642654012fSReza Sabdar 		cmd.uscsi_bufaddr = request->dataout.dataout_val;
13652654012fSReza Sabdar 		cmd.uscsi_buflen = request->dataout.dataout_len;
13662654012fSReza Sabdar 	} else {
136786c48bbfSReza Sabdar 		cmd.uscsi_flags = USCSI_RQENABLE;
13682654012fSReza Sabdar 		cmd.uscsi_bufaddr = 0;
13692654012fSReza Sabdar 		cmd.uscsi_buflen = 0;
1370*65451a03SReza Sabdar 	}
13712654012fSReza Sabdar 	cmd.uscsi_rqlen = sizeof (rq_buf);
13722654012fSReza Sabdar 	cmd.uscsi_rqbuf = rq_buf;
13732654012fSReza Sabdar 
13742654012fSReza Sabdar 	cmd.uscsi_timeout = (request->timeout < 1000) ?
13752654012fSReza Sabdar 	    1 : (request->timeout / 1000);
13762654012fSReza Sabdar 
13772654012fSReza Sabdar 	cmd.uscsi_cdb = (caddr_t)request->cdb.cdb_val;
13782654012fSReza Sabdar 	cmd.uscsi_cdblen = request->cdb.cdb_len;
13792654012fSReza Sabdar 
13802654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "cmd: 0x%x, len: %d, flags: %d, datain_len: %d",
13812654012fSReza Sabdar 	    request->cdb.cdb_val[0] & 0xff, request->cdb.cdb_len,
13822654012fSReza Sabdar 	    request->flags, request->datain_len);
13832654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "dataout_len: %d, timeout: %d",
13842654012fSReza Sabdar 	    request->dataout.dataout_len, request->timeout);
13852654012fSReza Sabdar 
13862654012fSReza Sabdar 	if (request->cdb.cdb_len > 12) {
13872654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
13882654012fSReza Sabdar 		ndmp_send_reply(session->ns_connection, (void *) &reply,
13892654012fSReza Sabdar 		    "sending execute_cdb reply");
13902654012fSReza Sabdar 		if (request->flags == NDMP_SCSI_DATA_IN)
13912654012fSReza Sabdar 			free(cmd.uscsi_bufaddr);
13922654012fSReza Sabdar 		return;
13932654012fSReza Sabdar 	}
13942654012fSReza Sabdar 
13952654012fSReza Sabdar 	reply.error = NDMP_NO_ERR;
13962654012fSReza Sabdar 
13972654012fSReza Sabdar 	if ((olp = ndmp_open_list_find(adapter_name, sid, lun)) != NULL) {
13982654012fSReza Sabdar 		fd = olp->ol_fd;
13992654012fSReza Sabdar 	} else {
14002654012fSReza Sabdar 		reply.error = NDMP_DEV_NOT_OPEN_ERR;
14012654012fSReza Sabdar 		ndmp_send_reply(session->ns_connection, (void *) &reply,
14022654012fSReza Sabdar 		    "sending execute_cdb reply");
14032654012fSReza Sabdar 		if (request->flags == NDMP_SCSI_DATA_IN)
14042654012fSReza Sabdar 			free(cmd.uscsi_bufaddr);
14052654012fSReza Sabdar 		return;
14062654012fSReza Sabdar 	}
14072654012fSReza Sabdar 
14082654012fSReza Sabdar 	if (ioctl(fd, USCSICMD, &cmd) < 0) {
1409674cb4b0SReza Sabdar 		if (errno != EIO && errno != 0)
1410674cb4b0SReza Sabdar 			NDMP_LOG(LOG_ERR,
1411674cb4b0SReza Sabdar 			    "Failed to send command to device: %m");
14122654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "ioctl(USCSICMD) error: %m");
14137a088f03SReza Sabdar 		if (cmd.uscsi_status == 0)
14142654012fSReza Sabdar 			reply.error = NDMP_IO_ERR;
14152654012fSReza Sabdar 	}
14162654012fSReza Sabdar 
14172654012fSReza Sabdar 	reply.status = cmd.uscsi_status;
14182654012fSReza Sabdar 
14192654012fSReza Sabdar 	if (request->flags == NDMP_SCSI_DATA_IN) {
14202654012fSReza Sabdar 		reply.datain.datain_len = cmd.uscsi_buflen;
14212654012fSReza Sabdar 		reply.datain.datain_val = cmd.uscsi_bufaddr;
14222654012fSReza Sabdar 	} else {
14232654012fSReza Sabdar 		reply.dataout_len = request->dataout.dataout_len;
14242654012fSReza Sabdar 	}
14252654012fSReza Sabdar 
14262654012fSReza Sabdar 	reply.ext_sense.ext_sense_len = cmd.uscsi_rqlen - cmd.uscsi_rqresid;
14272654012fSReza Sabdar 	reply.ext_sense.ext_sense_val = rq_buf;
14282654012fSReza Sabdar 
14292654012fSReza Sabdar 	if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
14302654012fSReza Sabdar 	    (void *)&reply) < 0)
14312654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Error sending scsi_execute_cdb reply.");
14322654012fSReza Sabdar 
14332654012fSReza Sabdar 	if (request->flags == NDMP_SCSI_DATA_IN)
14342654012fSReza Sabdar 		free(cmd.uscsi_bufaddr);
14352654012fSReza Sabdar }
14362654012fSReza Sabdar 
14372654012fSReza Sabdar 
14382654012fSReza Sabdar /*
14392654012fSReza Sabdar  * ndmp_stop_local_reader
14402654012fSReza Sabdar  *
14412654012fSReza Sabdar  * Stops a mover reader thread (for local backup only)
14422654012fSReza Sabdar  *
14432654012fSReza Sabdar  * Parameters:
14442654012fSReza Sabdar  *   session (input) - session pointer
14452654012fSReza Sabdar  *   cmds (input) - reader/writer command struct
14462654012fSReza Sabdar  *
14472654012fSReza Sabdar  * Returns:
14482654012fSReza Sabdar  *   void
14492654012fSReza Sabdar  */
14502654012fSReza Sabdar void
14512654012fSReza Sabdar ndmp_stop_local_reader(ndmpd_session_t *session, tlm_commands_t *cmds)
14522654012fSReza Sabdar {
14532654012fSReza Sabdar 	if (session != NULL) {
14542654012fSReza Sabdar 		if (session->ns_data.dd_sock == -1) {
14552654012fSReza Sabdar 			/*
14562654012fSReza Sabdar 			 * 2-way restore.
14572654012fSReza Sabdar 			 */
14582654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "2-way restore");
14592654012fSReza Sabdar 			if (cmds != NULL && cmds->tcs_reader_count > 0) {
14602654012fSReza Sabdar 				nlp_event_rv_set(session, -2);
14612654012fSReza Sabdar 				nlp_event_nw(session);
14622654012fSReza Sabdar 			}
14632654012fSReza Sabdar 		}
14642654012fSReza Sabdar 	}
14652654012fSReza Sabdar }
14662654012fSReza Sabdar 
14672654012fSReza Sabdar 
14682654012fSReza Sabdar /*
14692654012fSReza Sabdar  * Stops a mover reader thread (for remote backup only)
14702654012fSReza Sabdar  *
14712654012fSReza Sabdar  * Parameters:
14722654012fSReza Sabdar  *   session (input) - session pointer
14732654012fSReza Sabdar  *   cmds (input) - reader/writer command struct
14742654012fSReza Sabdar  *
14752654012fSReza Sabdar  * Returns:
14762654012fSReza Sabdar  *   void
14772654012fSReza Sabdar  */
14782654012fSReza Sabdar void
14792654012fSReza Sabdar ndmp_stop_remote_reader(ndmpd_session_t *session)
14802654012fSReza Sabdar {
14812654012fSReza Sabdar 	if (session != NULL) {
14822654012fSReza Sabdar 		if (session->ns_data.dd_sock >= 0) {
14832654012fSReza Sabdar 			/*
14842654012fSReza Sabdar 			 * 3-way restore.
14852654012fSReza Sabdar 			 */
14862654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG,
14872654012fSReza Sabdar 			    "data.sock: %d", session->ns_data.dd_sock);
14882654012fSReza Sabdar 			(void) close(session->ns_data.dd_sock);
14892654012fSReza Sabdar 			session->ns_data.dd_sock = -1;
14902654012fSReza Sabdar 		}
14912654012fSReza Sabdar 	}
14922654012fSReza Sabdar }
14932654012fSReza Sabdar 
14942654012fSReza Sabdar 
14952654012fSReza Sabdar /*
14962654012fSReza Sabdar  * ndmp_wait_for_reader
14972654012fSReza Sabdar  *
14982654012fSReza Sabdar  * Wait for a reader until get done (busy wait)
14992654012fSReza Sabdar  */
15002654012fSReza Sabdar void
15012654012fSReza Sabdar ndmp_wait_for_reader(tlm_commands_t *cmds)
15022654012fSReza Sabdar {
15032654012fSReza Sabdar 	if (cmds == NULL) {
15042654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "cmds == NULL");
15052654012fSReza Sabdar 	} else {
15062654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
15072654012fSReza Sabdar 		    "reader_count: %d", cmds->tcs_reader_count);
15082654012fSReza Sabdar 
15092654012fSReza Sabdar 		while (cmds->tcs_reader_count > 0)
15102654012fSReza Sabdar 			(void) sleep(1);
15112654012fSReza Sabdar 	}
15122654012fSReza Sabdar }
15132654012fSReza Sabdar 
15142654012fSReza Sabdar 
15152654012fSReza Sabdar /*
15162654012fSReza Sabdar  * ndmp_open_list_find
15172654012fSReza Sabdar  *
15182654012fSReza Sabdar  * Find a specific device in the open list
15192654012fSReza Sabdar  *
15202654012fSReza Sabdar  * Parameters:
15212654012fSReza Sabdar  *   dev (input) - device name
15222654012fSReza Sabdar  *   sid (input) - SCSI target ID
15232654012fSReza Sabdar  *   lun (input) - LUN number
15242654012fSReza Sabdar  *
15252654012fSReza Sabdar  * Returns:
15262654012fSReza Sabdar  *   pointer to the open list entry
15272654012fSReza Sabdar  */
15282654012fSReza Sabdar struct open_list *
15292654012fSReza Sabdar ndmp_open_list_find(char *dev, int sid, int lun)
15302654012fSReza Sabdar {
15312654012fSReza Sabdar 	struct ol_head *olhp;
15322654012fSReza Sabdar 	struct open_list *olp;
15332654012fSReza Sabdar 
15342654012fSReza Sabdar 	if (dev == NULL || *dev == '\0') {
15352654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid argument");
15362654012fSReza Sabdar 		return (NULL);
15372654012fSReza Sabdar 	}
15382654012fSReza Sabdar 
15392654012fSReza Sabdar 	(void) mutex_lock(&ol_mutex);
15402654012fSReza Sabdar 	olhp = &ol_head;
15412654012fSReza Sabdar 	for (olp = LIST_FIRST(olhp); olp != NULL; olp = LIST_NEXT(olp, ol_q))
15422654012fSReza Sabdar 		if (strcmp(olp->ol_devnm, dev) == 0 && olp->ol_sid == sid &&
15432654012fSReza Sabdar 		    olp->ol_lun == lun) {
15442654012fSReza Sabdar 			(void) mutex_unlock(&ol_mutex);
15452654012fSReza Sabdar 			return (olp);
15462654012fSReza Sabdar 		}
15472654012fSReza Sabdar 
15482654012fSReza Sabdar 	(void) mutex_unlock(&ol_mutex);
15492654012fSReza Sabdar 	return (NULL);
15502654012fSReza Sabdar }
15512654012fSReza Sabdar 
15522654012fSReza Sabdar 
15532654012fSReza Sabdar /*
15542654012fSReza Sabdar  * ndmp_open_list_add
15552654012fSReza Sabdar  *
15562654012fSReza Sabdar  * Add a specific device to the open list
15572654012fSReza Sabdar  *
15582654012fSReza Sabdar  * Parameters:
15592654012fSReza Sabdar  *   conn (input) - connection pointer
15602654012fSReza Sabdar  *   dev (input) - device name
15612654012fSReza Sabdar  *   sid (input) - SCSI target ID
15622654012fSReza Sabdar  *   lun (input) - LUN number
15632654012fSReza Sabdar  *   fd (input) - the device file descriptor
15642654012fSReza Sabdar  *
15652654012fSReza Sabdar  * Returns:
15662654012fSReza Sabdar  *   errno
15672654012fSReza Sabdar  */
15682654012fSReza Sabdar int
15692654012fSReza Sabdar ndmp_open_list_add(ndmp_connection_t *conn, char *dev, int sid, int lun, int fd)
15702654012fSReza Sabdar {
15712654012fSReza Sabdar 	int err;
15722654012fSReza Sabdar 	struct ol_head *olhp;
15732654012fSReza Sabdar 	struct open_list *olp;
15742654012fSReza Sabdar 
15752654012fSReza Sabdar 	if (dev == NULL || *dev == '\0') {
15762654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid argument");
15772654012fSReza Sabdar 		return (EINVAL);
15782654012fSReza Sabdar 	}
15792654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG,
15802654012fSReza Sabdar 	    "conn: 0x%08x, dev: %s, sid: %d, lun: %d", conn, dev, sid, lun);
15812654012fSReza Sabdar 
15822654012fSReza Sabdar 	err = 0;
15832654012fSReza Sabdar 	olhp = &ol_head;
15842654012fSReza Sabdar 
15852654012fSReza Sabdar 	if ((olp = ndmp_open_list_find(dev, sid, lun)) != NULL) {
15862654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "already in list");
15872654012fSReza Sabdar 		/*
15882654012fSReza Sabdar 		 * The adapter handle can be opened many times by the clients.
15892654012fSReza Sabdar 		 * Only when the target is set, we must check and reject the
15902654012fSReza Sabdar 		 * open request if the device is already being used by another
15912654012fSReza Sabdar 		 * session.
15922654012fSReza Sabdar 		 */
15932654012fSReza Sabdar 		if (sid == -1)
15942654012fSReza Sabdar 			olp->ol_nref++;
15952654012fSReza Sabdar 		else
15962654012fSReza Sabdar 			err = EBUSY;
15972654012fSReza Sabdar 	} else if ((olp = ndmp_malloc(sizeof (struct open_list))) == NULL) {
15982654012fSReza Sabdar 		err = ENOMEM;
15992654012fSReza Sabdar 	} else if ((olp->ol_devnm = strdup(dev)) == NULL) {
16002654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Out of memory.");
16012654012fSReza Sabdar 		free(olp);
16022654012fSReza Sabdar 		err = ENOMEM;
16032654012fSReza Sabdar 	} else {
16042654012fSReza Sabdar 		olp->cl_conn = conn;
16052654012fSReza Sabdar 		olp->ol_nref = 1;
16062654012fSReza Sabdar 		olp->ol_sid = sid;
16072654012fSReza Sabdar 		olp->ol_lun = lun;
16082654012fSReza Sabdar 		if (fd > 0)
16092654012fSReza Sabdar 			olp->ol_fd = fd;
16102654012fSReza Sabdar 		else
16112654012fSReza Sabdar 			olp->ol_fd = -1;
16122654012fSReza Sabdar 		(void) mutex_lock(&ol_mutex);
16132654012fSReza Sabdar 		LIST_INSERT_HEAD(olhp, olp, ol_q);
16142654012fSReza Sabdar 		(void) mutex_unlock(&ol_mutex);
16152654012fSReza Sabdar 	}
16162654012fSReza Sabdar 
16172654012fSReza Sabdar 	return (err);
16182654012fSReza Sabdar }
16192654012fSReza Sabdar 
16202654012fSReza Sabdar 
16212654012fSReza Sabdar /*
16222654012fSReza Sabdar  * ndmp_open_list_del
16232654012fSReza Sabdar  *
16242654012fSReza Sabdar  * Delete a specific device from the open list
16252654012fSReza Sabdar  *
16262654012fSReza Sabdar  * Parameters:
16272654012fSReza Sabdar  *   dev (input) - device name
16282654012fSReza Sabdar  *   sid (input) - SCSI target ID
16292654012fSReza Sabdar  *   lun (input) - LUN number
16302654012fSReza Sabdar  *
16312654012fSReza Sabdar  * Returns:
16322654012fSReza Sabdar  *   errno
16332654012fSReza Sabdar  */
16342654012fSReza Sabdar int
16352654012fSReza Sabdar ndmp_open_list_del(char *dev, int sid, int lun)
16362654012fSReza Sabdar {
16372654012fSReza Sabdar 	struct open_list *olp;
16382654012fSReza Sabdar 
16392654012fSReza Sabdar 	if (dev == NULL || *dev == '\0') {
16402654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid argument");
16412654012fSReza Sabdar 		return (EINVAL);
16422654012fSReza Sabdar 	}
16432654012fSReza Sabdar 	if ((olp = ndmp_open_list_find(dev, sid, lun)) == NULL) {
16442654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "%s not found", dev);
16452654012fSReza Sabdar 		return (ENOENT);
16462654012fSReza Sabdar 	}
16472654012fSReza Sabdar 
16482654012fSReza Sabdar 	(void) mutex_lock(&ol_mutex);
16492654012fSReza Sabdar 	if (--olp->ol_nref <= 0) {
16502654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
16512654012fSReza Sabdar 		    "Removed dev: %s, sid: %d, lun: %d", dev, sid, lun);
16522654012fSReza Sabdar 		LIST_REMOVE(olp, ol_q);
16532654012fSReza Sabdar 		free(olp->ol_devnm);
16542654012fSReza Sabdar 		free(olp);
16552654012fSReza Sabdar 	}
16562654012fSReza Sabdar 	(void) mutex_unlock(&ol_mutex);
16572654012fSReza Sabdar 
16582654012fSReza Sabdar 	return (0);
16592654012fSReza Sabdar }
16602654012fSReza Sabdar 
16612654012fSReza Sabdar 
16622654012fSReza Sabdar /*
16632654012fSReza Sabdar  * ndmp_open_list_release
16642654012fSReza Sabdar  *
16652654012fSReza Sabdar  * Close all the resources belonging to this connection.
16662654012fSReza Sabdar  *
16672654012fSReza Sabdar  * Parameters:
16682654012fSReza Sabdar  *    ndmp_connection_t *conn : connection identifier
16692654012fSReza Sabdar  *
16702654012fSReza Sabdar  * Returns:
16712654012fSReza Sabdar  *   void
16722654012fSReza Sabdar  */
16732654012fSReza Sabdar void
16742654012fSReza Sabdar ndmp_open_list_release(ndmp_connection_t *conn)
16752654012fSReza Sabdar {
16762654012fSReza Sabdar 	struct ol_head *olhp = &ol_head;
16772654012fSReza Sabdar 	struct open_list *olp;
16782654012fSReza Sabdar 	struct open_list *next;
16792654012fSReza Sabdar 
16802654012fSReza Sabdar 	(void) mutex_lock(&ol_mutex);
16812654012fSReza Sabdar 	olp = LIST_FIRST(olhp);
16822654012fSReza Sabdar 	while (olp != NULL) {
16832654012fSReza Sabdar 		next = LIST_NEXT(olp, ol_q);
16842654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "olp->conn 0x%08x", olp->cl_conn);
16852654012fSReza Sabdar 		if (olp->cl_conn == conn) {
16862654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG,
16872654012fSReza Sabdar 			    "Removed dev: %s, sid: %d, lun: %d",
16882654012fSReza Sabdar 			    olp->ol_devnm, olp->ol_sid, olp->ol_lun);
16892654012fSReza Sabdar 			LIST_REMOVE(olp, ol_q);
16902654012fSReza Sabdar 			if (olp->ol_fd > 0)
16912654012fSReza Sabdar 				(void) close(olp->ol_fd);
16922654012fSReza Sabdar 			free(olp->ol_devnm);
16932654012fSReza Sabdar 			free(olp);
16942654012fSReza Sabdar 		}
16952654012fSReza Sabdar 		olp = next;
16962654012fSReza Sabdar 	}
16972654012fSReza Sabdar 	(void) mutex_unlock(&ol_mutex);
16982654012fSReza Sabdar }
16992654012fSReza Sabdar 
17002654012fSReza Sabdar 
17012654012fSReza Sabdar /*
17022654012fSReza Sabdar  * ndmp_stop_buffer_worker
17032654012fSReza Sabdar  *
17042654012fSReza Sabdar  * Stop all reader and writer threads for a specific buffer.
17052654012fSReza Sabdar  *
17062654012fSReza Sabdar  * Parameters:
17072654012fSReza Sabdar  *   session (input) - session pointer
17082654012fSReza Sabdar  *
17092654012fSReza Sabdar  * Returns:
17102654012fSReza Sabdar  *   void
17112654012fSReza Sabdar  */
17122654012fSReza Sabdar void
17132654012fSReza Sabdar ndmp_stop_buffer_worker(ndmpd_session_t *session)
17142654012fSReza Sabdar {
17152654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
17162654012fSReza Sabdar 	tlm_commands_t *cmds;
17172654012fSReza Sabdar 
17182654012fSReza Sabdar 	session->ns_tape.td_pos = 0;
17192654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
17202654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
17212654012fSReza Sabdar 	} else {
17222654012fSReza Sabdar 		cmds = &nlp->nlp_cmds;
17232654012fSReza Sabdar 		if (cmds->tcs_command == NULL) {
17242654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "cmds->tcs_command == NULL");
17252654012fSReza Sabdar 		} else {
17262654012fSReza Sabdar 			cmds->tcs_reader = cmds->tcs_writer = TLM_ABORT;
17272654012fSReza Sabdar 			cmds->tcs_command->tc_reader = TLM_ABORT;
17282654012fSReza Sabdar 			cmds->tcs_command->tc_writer = TLM_ABORT;
17292654012fSReza Sabdar 			while (cmds->tcs_reader_count > 0 ||
17302654012fSReza Sabdar 			    cmds->tcs_writer_count > 0) {
17312654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
17322654012fSReza Sabdar 				    "trying to stop buffer worker");
17332654012fSReza Sabdar 				(void) sleep(1);
17342654012fSReza Sabdar 			}
17352654012fSReza Sabdar 		}
17362654012fSReza Sabdar 	}
17372654012fSReza Sabdar }
17382654012fSReza Sabdar 
17392654012fSReza Sabdar 
17402654012fSReza Sabdar /*
17412654012fSReza Sabdar  * ndmp_stop_reader_thread
17422654012fSReza Sabdar  *
17432654012fSReza Sabdar  * Stop only the reader threads of a specific buffer
17442654012fSReza Sabdar  *
17452654012fSReza Sabdar  * Parameters:
17462654012fSReza Sabdar  *   session (input) - session pointer
17472654012fSReza Sabdar  *
17482654012fSReza Sabdar  * Returns:
17492654012fSReza Sabdar  *   void
17502654012fSReza Sabdar  */
17512654012fSReza Sabdar void
17522654012fSReza Sabdar ndmp_stop_reader_thread(ndmpd_session_t *session)
17532654012fSReza Sabdar {
17542654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
17552654012fSReza Sabdar 	tlm_commands_t *cmds;
17562654012fSReza Sabdar 
17572654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
17582654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
17592654012fSReza Sabdar 	} else {
17602654012fSReza Sabdar 		cmds = &nlp->nlp_cmds;
17612654012fSReza Sabdar 		if (cmds->tcs_command == NULL) {
17622654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "cmds->tcs_command == NULL");
17632654012fSReza Sabdar 		} else {
17642654012fSReza Sabdar 			cmds->tcs_reader = TLM_ABORT;
17652654012fSReza Sabdar 			cmds->tcs_command->tc_reader = TLM_ABORT;
17662654012fSReza Sabdar 			while (cmds->tcs_reader_count > 0) {
17672654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
17682654012fSReza Sabdar 				    "trying to stop reader thread");
17692654012fSReza Sabdar 				(void) sleep(1);
17702654012fSReza Sabdar 			}
17712654012fSReza Sabdar 		}
17722654012fSReza Sabdar 	}
17732654012fSReza Sabdar }
17742654012fSReza Sabdar 
17752654012fSReza Sabdar 
17762654012fSReza Sabdar /*
17772654012fSReza Sabdar  * ndmp_stop_reader_thread
17782654012fSReza Sabdar  *
17792654012fSReza Sabdar  * Stop only the writer threads of a specific buffer
17802654012fSReza Sabdar  *
17812654012fSReza Sabdar  * Parameters:
17822654012fSReza Sabdar  *   session (input) - session pointer
17832654012fSReza Sabdar  *
17842654012fSReza Sabdar  * Returns:
17852654012fSReza Sabdar  *   void
17862654012fSReza Sabdar  */
17872654012fSReza Sabdar void
17882654012fSReza Sabdar ndmp_stop_writer_thread(ndmpd_session_t *session)
17892654012fSReza Sabdar {
17902654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
17912654012fSReza Sabdar 	tlm_commands_t *cmds;
17922654012fSReza Sabdar 
17932654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
17942654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
17952654012fSReza Sabdar 	} else {
17962654012fSReza Sabdar 		cmds = &nlp->nlp_cmds;
17972654012fSReza Sabdar 		if (cmds->tcs_command == NULL) {
17982654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "cmds->tcs_command == NULL");
17992654012fSReza Sabdar 		} else {
18002654012fSReza Sabdar 			cmds->tcs_writer = TLM_ABORT;
18012654012fSReza Sabdar 			cmds->tcs_command->tc_writer = TLM_ABORT;
18022654012fSReza Sabdar 			while (cmds->tcs_writer_count > 0) {
18032654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
18042654012fSReza Sabdar 				    "trying to stop writer thread");
18052654012fSReza Sabdar 				(void) sleep(1);
18062654012fSReza Sabdar 			}
18072654012fSReza Sabdar 		}
18082654012fSReza Sabdar 	}
18092654012fSReza Sabdar }
18102654012fSReza Sabdar 
18112654012fSReza Sabdar 
18122654012fSReza Sabdar /*
18132654012fSReza Sabdar  * ndmp_free_reader_writer_ipc
18142654012fSReza Sabdar  *
18152654012fSReza Sabdar  * Free and release the reader/writer buffers and the IPC structure
18162654012fSReza Sabdar  * for reader and writer threads.
18172654012fSReza Sabdar  *
18182654012fSReza Sabdar  * Parameters:
18192654012fSReza Sabdar  *   session (input) - session pointer
18202654012fSReza Sabdar  *
18212654012fSReza Sabdar  * Returns:
18222654012fSReza Sabdar  *   void
18232654012fSReza Sabdar  */
18242654012fSReza Sabdar void
18252654012fSReza Sabdar ndmp_free_reader_writer_ipc(ndmpd_session_t *session)
18262654012fSReza Sabdar {
18272654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
18282654012fSReza Sabdar 	tlm_commands_t *cmds;
18292654012fSReza Sabdar 
18302654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) != NULL) {
18312654012fSReza Sabdar 		cmds = &nlp->nlp_cmds;
18322654012fSReza Sabdar 		if (cmds->tcs_command != NULL) {
18332654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "cmds->tcs_command->tc_ref: %d",
18342654012fSReza Sabdar 			    cmds->tcs_command->tc_ref);
18352654012fSReza Sabdar 			tlm_release_reader_writer_ipc(cmds->tcs_command);
18362654012fSReza Sabdar 		}
18372654012fSReza Sabdar 	}
18382654012fSReza Sabdar }
18392654012fSReza Sabdar 
18402654012fSReza Sabdar 
18412654012fSReza Sabdar /*
18422654012fSReza Sabdar  * ndmp_waitfor_op
18432654012fSReza Sabdar  *
18442654012fSReza Sabdar  * Wait for a session reference count to drop to zero
18452654012fSReza Sabdar  *
18462654012fSReza Sabdar  * Parameters:
18472654012fSReza Sabdar  *   session (input) - session pointer
18482654012fSReza Sabdar  *
18492654012fSReza Sabdar  * Returns:
18502654012fSReza Sabdar  *   void
18512654012fSReza Sabdar  */
18522654012fSReza Sabdar void
18532654012fSReza Sabdar ndmp_waitfor_op(ndmpd_session_t *session)
18542654012fSReza Sabdar {
18552654012fSReza Sabdar 	if (session != NULL) {
18562654012fSReza Sabdar 		while (session->ns_nref > 0) {
18572654012fSReza Sabdar 			(void) sleep(1);
18582654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG,
18592654012fSReza Sabdar 			    "waiting for session nref: %d", session->ns_nref);
18602654012fSReza Sabdar 		}
18612654012fSReza Sabdar 	}
18622654012fSReza Sabdar }
18632654012fSReza Sabdar 
18642654012fSReza Sabdar 
18652654012fSReza Sabdar /*
18662654012fSReza Sabdar  * ndmp_session_ref
18672654012fSReza Sabdar  *
18682654012fSReza Sabdar  * Increment the reference count of the session
18692654012fSReza Sabdar  *
18702654012fSReza Sabdar  * Parameters:
18712654012fSReza Sabdar  *   session (input) - session pointer
18722654012fSReza Sabdar  *
18732654012fSReza Sabdar  * Returns:
18742654012fSReza Sabdar  *   void
18752654012fSReza Sabdar  */
18762654012fSReza Sabdar void
18772654012fSReza Sabdar ndmp_session_ref(ndmpd_session_t *session)
18782654012fSReza Sabdar {
18792654012fSReza Sabdar 	(void) mutex_lock(&session->ns_lock);
18802654012fSReza Sabdar 	session->ns_nref++;
18812654012fSReza Sabdar 	(void) mutex_unlock(&session->ns_lock);
18822654012fSReza Sabdar }
18832654012fSReza Sabdar 
18842654012fSReza Sabdar 
18852654012fSReza Sabdar /*
18862654012fSReza Sabdar  * ndmp_session_unref
18872654012fSReza Sabdar  *
18882654012fSReza Sabdar  * Decrement the reference count of the session
18892654012fSReza Sabdar  *
18902654012fSReza Sabdar  * Parameters:
18912654012fSReza Sabdar  *   session (input) - session pointer
18922654012fSReza Sabdar  *
18932654012fSReza Sabdar  * Returns:
18942654012fSReza Sabdar  *   void
18952654012fSReza Sabdar  */
18962654012fSReza Sabdar void
18972654012fSReza Sabdar ndmp_session_unref(ndmpd_session_t *session)
18982654012fSReza Sabdar {
18992654012fSReza Sabdar 	(void) mutex_lock(&session->ns_lock);
19002654012fSReza Sabdar 	session->ns_nref--;
19012654012fSReza Sabdar 	(void) mutex_unlock(&session->ns_lock);
19022654012fSReza Sabdar }
19032654012fSReza Sabdar 
19042654012fSReza Sabdar 
19052654012fSReza Sabdar /*
19062654012fSReza Sabdar  * ndmp_addr2str_v3
19072654012fSReza Sabdar  *
19082654012fSReza Sabdar  * Convert the address type to a string
19092654012fSReza Sabdar  *
19102654012fSReza Sabdar  * Parameters:
19112654012fSReza Sabdar  *   type (input) - address type
19122654012fSReza Sabdar  *
19132654012fSReza Sabdar  * Returns:
19142654012fSReza Sabdar  *   type in string
19152654012fSReza Sabdar  */
19162654012fSReza Sabdar char *
19172654012fSReza Sabdar ndmp_addr2str_v3(ndmp_addr_type type)
19182654012fSReza Sabdar {
19192654012fSReza Sabdar 	char *rv;
19202654012fSReza Sabdar 
19212654012fSReza Sabdar 	switch (type) {
19222654012fSReza Sabdar 	case NDMP_ADDR_LOCAL:
19232654012fSReza Sabdar 		rv = "Local";
19242654012fSReza Sabdar 		break;
19252654012fSReza Sabdar 	case NDMP_ADDR_TCP:
19262654012fSReza Sabdar 		rv = "TCP";
19272654012fSReza Sabdar 		break;
19282654012fSReza Sabdar 	case NDMP_ADDR_FC:
19292654012fSReza Sabdar 		rv = "FC";
19302654012fSReza Sabdar 		break;
19312654012fSReza Sabdar 	case NDMP_ADDR_IPC:
19322654012fSReza Sabdar 		rv = "IPC";
19332654012fSReza Sabdar 		break;
19342654012fSReza Sabdar 	default:
19352654012fSReza Sabdar 		rv = "Unknown";
19362654012fSReza Sabdar 	}
19372654012fSReza Sabdar 
19382654012fSReza Sabdar 	return (rv);
19392654012fSReza Sabdar }
19402654012fSReza Sabdar 
19412654012fSReza Sabdar 
19422654012fSReza Sabdar /*
19432654012fSReza Sabdar  * ndmp_valid_v3addr_type
19442654012fSReza Sabdar  *
19452654012fSReza Sabdar  * Make sure that the NDMP address is from any of the
19462654012fSReza Sabdar  * valid types
19472654012fSReza Sabdar  *
19482654012fSReza Sabdar  * Parameters:
19492654012fSReza Sabdar  *   type (input) - address type
19502654012fSReza Sabdar  *
19512654012fSReza Sabdar  * Returns:
19522654012fSReza Sabdar  *   1: valid
19532654012fSReza Sabdar  *   0: invalid
19542654012fSReza Sabdar  */
19552654012fSReza Sabdar boolean_t
19562654012fSReza Sabdar ndmp_valid_v3addr_type(ndmp_addr_type type)
19572654012fSReza Sabdar {
19582654012fSReza Sabdar 	boolean_t rv;
19592654012fSReza Sabdar 
19602654012fSReza Sabdar 	switch (type) {
19612654012fSReza Sabdar 	case NDMP_ADDR_LOCAL:
19622654012fSReza Sabdar 	case NDMP_ADDR_TCP:
19632654012fSReza Sabdar 	case NDMP_ADDR_FC:
19642654012fSReza Sabdar 	case NDMP_ADDR_IPC:
19652654012fSReza Sabdar 		rv = TRUE;
19662654012fSReza Sabdar 		break;
19672654012fSReza Sabdar 	default:
19682654012fSReza Sabdar 		rv = FALSE;
19692654012fSReza Sabdar 	}
19702654012fSReza Sabdar 
19712654012fSReza Sabdar 	return (rv);
19722654012fSReza Sabdar }
19732654012fSReza Sabdar 
19742654012fSReza Sabdar 
19752654012fSReza Sabdar /*
19762654012fSReza Sabdar  * ndmp_copy_addr_v3
19772654012fSReza Sabdar  *
19782654012fSReza Sabdar  * Copy NDMP address from source to destination (V2 and V3 only)
19792654012fSReza Sabdar  *
19802654012fSReza Sabdar  * Parameters:
19812654012fSReza Sabdar  *   dst (ouput) - destination address
19822654012fSReza Sabdar  *   src (input) - source address
19832654012fSReza Sabdar  *
19842654012fSReza Sabdar  * Returns:
19852654012fSReza Sabdar  *   void
19862654012fSReza Sabdar  */
19872654012fSReza Sabdar void
19882654012fSReza Sabdar ndmp_copy_addr_v3(ndmp_addr_v3 *dst, ndmp_addr_v3 *src)
19892654012fSReza Sabdar {
19902654012fSReza Sabdar 	dst->addr_type = src->addr_type;
19912654012fSReza Sabdar 	switch (src->addr_type) {
19922654012fSReza Sabdar 	case NDMP_ADDR_LOCAL:
19932654012fSReza Sabdar 		/* nothing */
19942654012fSReza Sabdar 		break;
19952654012fSReza Sabdar 	case NDMP_ADDR_TCP:
19962654012fSReza Sabdar 		dst->tcp_ip_v3 = htonl(src->tcp_ip_v3);
19972654012fSReza Sabdar 		dst->tcp_port_v3 = src->tcp_port_v3;
19982654012fSReza Sabdar 		break;
19992654012fSReza Sabdar 	case NDMP_ADDR_FC:
20002654012fSReza Sabdar 	case NDMP_ADDR_IPC:
20012654012fSReza Sabdar 	default:
20022654012fSReza Sabdar 		break;
20032654012fSReza Sabdar 	}
20042654012fSReza Sabdar }
20052654012fSReza Sabdar 
20062654012fSReza Sabdar 
20072654012fSReza Sabdar /*
20082654012fSReza Sabdar  * ndmp_copy_addr_v4
20092654012fSReza Sabdar  *
20102654012fSReza Sabdar  * Copy NDMP address from source to destination. V4 has a extra
20112654012fSReza Sabdar  * environment list inside the address too which needs to be copied.
20122654012fSReza Sabdar  *
20132654012fSReza Sabdar  * Parameters:
20142654012fSReza Sabdar  *   dst (ouput) - destination address
20152654012fSReza Sabdar  *   src (input) - source address
20162654012fSReza Sabdar  *
20172654012fSReza Sabdar  * Returns:
20182654012fSReza Sabdar  *   void
20192654012fSReza Sabdar  */
20202654012fSReza Sabdar void
20212654012fSReza Sabdar ndmp_copy_addr_v4(ndmp_addr_v4 *dst, ndmp_addr_v4 *src)
20222654012fSReza Sabdar {
20232654012fSReza Sabdar 	int i;
20242654012fSReza Sabdar 
20252654012fSReza Sabdar 	dst->addr_type = src->addr_type;
20262654012fSReza Sabdar 	dst->tcp_len_v4 = src->tcp_len_v4;
20272654012fSReza Sabdar 	switch (src->addr_type) {
20282654012fSReza Sabdar 	case NDMP_ADDR_LOCAL:
20292654012fSReza Sabdar 		/* nothing */
20302654012fSReza Sabdar 		break;
20312654012fSReza Sabdar 	case NDMP_ADDR_TCP:
20322654012fSReza Sabdar 		dst->tcp_addr_v4 = ndmp_malloc(sizeof (ndmp_tcp_addr_v4) *
20332654012fSReza Sabdar 		    src->tcp_len_v4);
20342654012fSReza Sabdar 		if (dst->tcp_addr_v4 == 0)
20352654012fSReza Sabdar 			return;
20362654012fSReza Sabdar 
20372654012fSReza Sabdar 		for (i = 0; i < src->tcp_len_v4; i++) {
20382654012fSReza Sabdar 			dst->tcp_ip_v4(i) = htonl(src->tcp_ip_v4(i));
20392654012fSReza Sabdar 			dst->tcp_port_v4(i) = src->tcp_port_v4(i);
20402654012fSReza Sabdar 			dst->tcp_env_v4(i).addr_env_len = 0; /* Solaris */
20412654012fSReza Sabdar 			dst->tcp_env_v4(i).addr_env_val = 0; /* Solaris */
20422654012fSReza Sabdar 		}
20432654012fSReza Sabdar 		break;
20442654012fSReza Sabdar 	case NDMP_ADDR_FC:
20452654012fSReza Sabdar 	case NDMP_ADDR_IPC:
20462654012fSReza Sabdar 	default:
20472654012fSReza Sabdar 		break;
20482654012fSReza Sabdar 	}
20492654012fSReza Sabdar }
20502654012fSReza Sabdar 
20512654012fSReza Sabdar 
20522654012fSReza Sabdar /*
20532654012fSReza Sabdar  * ndmp_connect_sock_v3
20542654012fSReza Sabdar  *
20552654012fSReza Sabdar  * Creates a socket and connects to the specified address/port
20562654012fSReza Sabdar  *
20572654012fSReza Sabdar  * Parameters:
20582654012fSReza Sabdar  *   addr (input) - IP address
20592654012fSReza Sabdar  *   port (input) - port number
20602654012fSReza Sabdar  *
20612654012fSReza Sabdar  * Returns:
20622654012fSReza Sabdar  *   0: on success
20632654012fSReza Sabdar  *  -1: otherwise
20642654012fSReza Sabdar  */
20652654012fSReza Sabdar int
20662654012fSReza Sabdar ndmp_connect_sock_v3(ulong_t addr, ushort_t port)
20672654012fSReza Sabdar {
20682654012fSReza Sabdar 	int sock;
20692654012fSReza Sabdar 	struct sockaddr_in sin;
20702654012fSReza Sabdar 	int flag = 1;
20712654012fSReza Sabdar 
20722654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "addr %s:%d", inet_ntoa(IN_ADDR(addr)), port);
20732654012fSReza Sabdar 
20742654012fSReza Sabdar 	sock = socket(AF_INET, SOCK_STREAM, 0);
20752654012fSReza Sabdar 	if (sock < 0) {
20762654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Socket error: %m");
20772654012fSReza Sabdar 		return (-1);
20782654012fSReza Sabdar 	}
20792654012fSReza Sabdar 
20802654012fSReza Sabdar 	(void) memset((void *) &sin, 0, sizeof (sin));
20812654012fSReza Sabdar 	sin.sin_family = AF_INET;
20822654012fSReza Sabdar 	sin.sin_addr.s_addr = htonl(addr);
20832654012fSReza Sabdar 	sin.sin_port = htons(port);
20842654012fSReza Sabdar 	if (connect(sock, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
20852654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Connect error: %m");
20862654012fSReza Sabdar 		(void) close(sock);
20872654012fSReza Sabdar 		sock = -1;
20882654012fSReza Sabdar 	} else {
20892654012fSReza Sabdar 		if (ndmp_sbs > 0)
20902654012fSReza Sabdar 			ndmp_set_socket_snd_buf(sock, ndmp_sbs*KILOBYTE);
20912654012fSReza Sabdar 		if (ndmp_rbs > 0)
20922654012fSReza Sabdar 			ndmp_set_socket_rcv_buf(sock, ndmp_rbs*KILOBYTE);
20932654012fSReza Sabdar 
20942654012fSReza Sabdar 		ndmp_set_socket_nodelay(sock);
20952654012fSReza Sabdar 		(void) setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &flag,
20962654012fSReza Sabdar 		    sizeof (flag));
20972654012fSReza Sabdar 
20982654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "sock %d", sock);
20992654012fSReza Sabdar 	}
21002654012fSReza Sabdar 
21012654012fSReza Sabdar 	return (sock);
21022654012fSReza Sabdar }
21032654012fSReza Sabdar 
21042654012fSReza Sabdar /*
21052654012fSReza Sabdar  * ndmp_create_socket
21062654012fSReza Sabdar  *
21072654012fSReza Sabdar  * Creates a socket for listening for accepting data connections.
21082654012fSReza Sabdar  *
21092654012fSReza Sabdar  * Parameters:
21102654012fSReza Sabdar  *   session (input)  - session pointer.
21112654012fSReza Sabdar  *   addr    (output) - location to store address of socket.
21122654012fSReza Sabdar  *   port    (output) - location to store port of socket.
21132654012fSReza Sabdar  *
21142654012fSReza Sabdar  * Returns:
21152654012fSReza Sabdar  *   0 - success.
21162654012fSReza Sabdar  *  -1 - error.
21172654012fSReza Sabdar  */
21182654012fSReza Sabdar int
21192654012fSReza Sabdar ndmp_create_socket(ulong_t *addr, ushort_t *port)
21202654012fSReza Sabdar {
21212654012fSReza Sabdar 	char *p;
21222654012fSReza Sabdar 	int length;
21232654012fSReza Sabdar 	int sd;
21242654012fSReza Sabdar 	struct sockaddr_in sin;
21252654012fSReza Sabdar 
2126588541fbSReza Sabdar 	/* Try the user's prefered NIC IP address */
21272654012fSReza Sabdar 	p = ndmpd_get_prop(NDMP_MOVER_NIC);
21282654012fSReza Sabdar 
2129588541fbSReza Sabdar 	/* Try host's IP address */
21302654012fSReza Sabdar 	if (!p || *p == 0)
21312654012fSReza Sabdar 		p = gethostaddr();
21322654012fSReza Sabdar 
2133588541fbSReza Sabdar 	/* Try default NIC's IP address (if DNS failed) */
2134588541fbSReza Sabdar 	if (!p)
2135588541fbSReza Sabdar 		p = get_default_nic_addr();
2136588541fbSReza Sabdar 
2137588541fbSReza Sabdar 	/* Fail if no IP can be obtained */
21382654012fSReza Sabdar 	if (!p) {
21392654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Undetermined network port.");
21402654012fSReza Sabdar 		return (-1);
21412654012fSReza Sabdar 	}
21422654012fSReza Sabdar 
21432654012fSReza Sabdar 	*addr = inet_addr(p);
21442654012fSReza Sabdar 
21452654012fSReza Sabdar 	sd = socket(AF_INET, SOCK_STREAM, 0);
21462654012fSReza Sabdar 	if (sd < 0) {
21472654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Socket error: %m");
21482654012fSReza Sabdar 		return (-1);
21492654012fSReza Sabdar 	}
21502654012fSReza Sabdar 	sin.sin_family = AF_INET;
21512654012fSReza Sabdar 	sin.sin_addr.s_addr = INADDR_ANY;
21522654012fSReza Sabdar 	sin.sin_port = 0;
21532654012fSReza Sabdar 	length = sizeof (sin);
21542654012fSReza Sabdar 
21552654012fSReza Sabdar 	if (bind(sd, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
21562654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Bind error: %m");
21572654012fSReza Sabdar 		(void) close(sd);
21582654012fSReza Sabdar 		sd = -1;
21592654012fSReza Sabdar 	} else if (getsockname(sd, (struct sockaddr *)&sin, &length) < 0) {
21602654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "getsockname error: %m");
21612654012fSReza Sabdar 		(void) close(sd);
21622654012fSReza Sabdar 		sd = -1;
21632654012fSReza Sabdar 	} else if (listen(sd, 5) < 0) {
21642654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Listen error: %m");
21652654012fSReza Sabdar 		(void) close(sd);
21662654012fSReza Sabdar 		sd = -1;
21672654012fSReza Sabdar 	} else
21682654012fSReza Sabdar 		*port = sin.sin_port;
21692654012fSReza Sabdar 
21702654012fSReza Sabdar 	return (sd);
21712654012fSReza Sabdar }
21722654012fSReza Sabdar 
21732654012fSReza Sabdar 
21742654012fSReza Sabdar /*
21752654012fSReza Sabdar  * cctime
21762654012fSReza Sabdar  *
21772654012fSReza Sabdar  * Convert the specified time into a string.  It's like
21782654012fSReza Sabdar  * ctime(), but:
21792654012fSReza Sabdar  *     - chops the trailing '\n' of ctime.
21802654012fSReza Sabdar  *     - and returns "the epoch" if time is 0.
21812654012fSReza Sabdar  *
21822654012fSReza Sabdar  * Returns:
21832654012fSReza Sabdar  *     "": invalid argument.
21842654012fSReza Sabdar  *     "the epoch": if time is 0.
21852654012fSReza Sabdar  *     string format of the time.
21862654012fSReza Sabdar  */
21872654012fSReza Sabdar char *
21882654012fSReza Sabdar cctime(time_t *t)
21892654012fSReza Sabdar {
21902654012fSReza Sabdar 	char *bp, *cp;
219189f9eb87SReza Sabdar 	static char tbuf[BUFSIZ];
21922654012fSReza Sabdar 
21932654012fSReza Sabdar 	if (!t)
21942654012fSReza Sabdar 		return ("");
21952654012fSReza Sabdar 
21962654012fSReza Sabdar 	if (*t == (time_t)0)
21972654012fSReza Sabdar 		return ("the epoch");
21982654012fSReza Sabdar 
219989f9eb87SReza Sabdar 	if ((bp = ctime_r(t, tbuf, BUFSIZ)) == NULL)
220089f9eb87SReza Sabdar 		return ("");
220189f9eb87SReza Sabdar 
22022654012fSReza Sabdar 	cp = strchr(bp, '\n');
22032654012fSReza Sabdar 	if (cp)
22042654012fSReza Sabdar 		*cp = '\0';
22052654012fSReza Sabdar 
22062654012fSReza Sabdar 	return (bp);
22072654012fSReza Sabdar }
22082654012fSReza Sabdar 
22092654012fSReza Sabdar 
22102654012fSReza Sabdar /*
22112654012fSReza Sabdar  * ndmp_new_job_name
22122654012fSReza Sabdar  *
22132654012fSReza Sabdar  * Create a job name for each backup/restore to keep track
22142654012fSReza Sabdar  *
22152654012fSReza Sabdar  * Parameters:
22162654012fSReza Sabdar  *   jname (output) - job name
22172654012fSReza Sabdar  *
22182654012fSReza Sabdar  * Returns:
22192654012fSReza Sabdar  *   jname
22202654012fSReza Sabdar  */
22212654012fSReza Sabdar char *
22222654012fSReza Sabdar ndmp_new_job_name(char *jname)
22232654012fSReza Sabdar {
22242654012fSReza Sabdar 	if (jname != NULL) {
22252654012fSReza Sabdar 		(void) snprintf(jname, TLM_MAX_BACKUP_JOB_NAME, "%s%d",
22262654012fSReza Sabdar 		    NDMP_RCF_BASENAME, ndmp_job_cnt++);
22272654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "jname: \"%s\"", jname);
22282654012fSReza Sabdar 	}
22292654012fSReza Sabdar 
22302654012fSReza Sabdar 	return (jname);
22312654012fSReza Sabdar }
22322654012fSReza Sabdar 
22332654012fSReza Sabdar 
22342654012fSReza Sabdar /*
22352654012fSReza Sabdar  * fs_is_valid_logvol
22362654012fSReza Sabdar  *
22372654012fSReza Sabdar  * Check if the log path exists
22382654012fSReza Sabdar  *
22392654012fSReza Sabdar  * Parameters:
22402654012fSReza Sabdar  *   path (input) - log path
22412654012fSReza Sabdar  *
22422654012fSReza Sabdar  * Returns:
22432654012fSReza Sabdar  *   FALSE: invalid
22442654012fSReza Sabdar  *   TRUE: valid
22452654012fSReza Sabdar  */
22462654012fSReza Sabdar boolean_t
22472654012fSReza Sabdar fs_is_valid_logvol(char *path)
22482654012fSReza Sabdar {
22492654012fSReza Sabdar 	struct stat64 st;
22502654012fSReza Sabdar 
22512654012fSReza Sabdar 	if (stat64(path, &st) < 0)
22522654012fSReza Sabdar 		return (FALSE);
22532654012fSReza Sabdar 
22542654012fSReza Sabdar 	return (TRUE);
22552654012fSReza Sabdar }
22562654012fSReza Sabdar 
22572654012fSReza Sabdar 
22582654012fSReza Sabdar /*
22592654012fSReza Sabdar  * ndmpd_mk_temp
22602654012fSReza Sabdar  *
22612654012fSReza Sabdar  * Make a temporary file using the working directory path and the
22622654012fSReza Sabdar  * jobname
22632654012fSReza Sabdar  *
22642654012fSReza Sabdar  * Parameters:
22652654012fSReza Sabdar  *   buf (output) - the temporary file name path
22662654012fSReza Sabdar  *
22672654012fSReza Sabdar  * Returns:
22682654012fSReza Sabdar  *   buf
22692654012fSReza Sabdar  */
22702654012fSReza Sabdar char *
22712654012fSReza Sabdar ndmpd_mk_temp(char *buf)
22722654012fSReza Sabdar {
22732654012fSReza Sabdar 	char fname[TLM_MAX_BACKUP_JOB_NAME];
22742654012fSReza Sabdar 	const char *dir;
22752654012fSReza Sabdar 	char *rv;
22762654012fSReza Sabdar 
22772654012fSReza Sabdar 	if (!buf)
22782654012fSReza Sabdar 		return (NULL);
22792654012fSReza Sabdar 
22802654012fSReza Sabdar 	dir = ndmpd_get_prop(NDMP_DEBUG_PATH);
22812654012fSReza Sabdar 	if (dir == 0 || *dir == '\0') {
22822654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "NDMP work path not specified");
22832654012fSReza Sabdar 		return (0);
22842654012fSReza Sabdar 	}
22852654012fSReza Sabdar 
22862654012fSReza Sabdar 	if (!fs_is_valid_logvol((char *)dir)) {
22872654012fSReza Sabdar 		NDMP_LOG(LOG_ERR,
22882654012fSReza Sabdar 		    "Log file path cannot be on system volumes.");
22892654012fSReza Sabdar 		return (0);
22902654012fSReza Sabdar 	}
22912654012fSReza Sabdar 
22922654012fSReza Sabdar 	dir += strspn(dir, " \t");
22932654012fSReza Sabdar 	if (!*dir) {
22942654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "NDMP work path not specified");
22952654012fSReza Sabdar 		return (0);
22962654012fSReza Sabdar 	}
22972654012fSReza Sabdar 
22982654012fSReza Sabdar 	rv = buf;
22992654012fSReza Sabdar 	(void) ndmp_new_job_name(fname);
23002654012fSReza Sabdar 	(void) tlm_cat_path(buf, (char *)dir, fname);
23012654012fSReza Sabdar 
23022654012fSReza Sabdar 	return (rv);
23032654012fSReza Sabdar }
23042654012fSReza Sabdar 
23052654012fSReza Sabdar 
23062654012fSReza Sabdar /*
23072654012fSReza Sabdar  * ndmpd_make_bk_dir_path
23082654012fSReza Sabdar  *
23092654012fSReza Sabdar  * Make a directory path for temporary files under the NDMP
23102654012fSReza Sabdar  * working directory.
23112654012fSReza Sabdar  *
23122654012fSReza Sabdar  * Parameters:
23132654012fSReza Sabdar  *   buf (output) - result path
23142654012fSReza Sabdar  *   fname (input) - the file name
23152654012fSReza Sabdar  *
23162654012fSReza Sabdar  * Returns:
23172654012fSReza Sabdar  *   buf
23182654012fSReza Sabdar  */
23192654012fSReza Sabdar char *
23202654012fSReza Sabdar ndmpd_make_bk_dir_path(char *buf, char *fname)
23212654012fSReza Sabdar {
23222654012fSReza Sabdar 	const char *p;
23232654012fSReza Sabdar 	char *name;
23242654012fSReza Sabdar 	char path[PATH_MAX];
23252654012fSReza Sabdar 
23262654012fSReza Sabdar 	if (!buf || !fname || !*fname)
23272654012fSReza Sabdar 		return (NULL);
23282654012fSReza Sabdar 
23292654012fSReza Sabdar 	p = ndmpd_get_prop(NDMP_DEBUG_PATH);
23302654012fSReza Sabdar 	if (p == NULL || *p == '\0' || !fs_is_valid_logvol((char *)p)) {
23312654012fSReza Sabdar 		return (NULL);
23322654012fSReza Sabdar 	}
23332654012fSReza Sabdar 
23342654012fSReza Sabdar 	(void) strlcpy(path, (char *)p, PATH_MAX);
23352654012fSReza Sabdar 	(void) trim_whitespace(path);
23362654012fSReza Sabdar 
23372654012fSReza Sabdar 	if ((name = strrchr(fname, '/')) == 0)
23382654012fSReza Sabdar 		name = fname;
23392654012fSReza Sabdar 
23402654012fSReza Sabdar 	(void) tlm_cat_path(buf, path, name);
23412654012fSReza Sabdar 	return (buf);
23422654012fSReza Sabdar }
23432654012fSReza Sabdar 
23442654012fSReza Sabdar 
23452654012fSReza Sabdar /*
23462654012fSReza Sabdar  * ndmp_is_chkpnt_root
23472654012fSReza Sabdar  *
23482654012fSReza Sabdar  * Is this a root checkpoint (snapshot) directory.
23492654012fSReza Sabdar  * Note: a temporary function
23502654012fSReza Sabdar  */
23512654012fSReza Sabdar boolean_t
23522654012fSReza Sabdar ndmp_is_chkpnt_root(char *path)
23532654012fSReza Sabdar {
23542654012fSReza Sabdar 	struct stat64 st;
23552654012fSReza Sabdar 
23562654012fSReza Sabdar 	if (stat64(path, &st) != 0) {
23572654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Couldn't stat path \"%s\"", path);
23582654012fSReza Sabdar 		return (TRUE);
23592654012fSReza Sabdar 	}
23602654012fSReza Sabdar 	return (FALSE);
23612654012fSReza Sabdar }
23622654012fSReza Sabdar 
23632654012fSReza Sabdar 
23642654012fSReza Sabdar /*
23652654012fSReza Sabdar  * ndmpd_make_exc_list
23662654012fSReza Sabdar  *
23672654012fSReza Sabdar  * Make a list of files that should not be backed up.
23682654012fSReza Sabdar  *
23692654012fSReza Sabdar  * Parameters:
23702654012fSReza Sabdar  *   void
23712654012fSReza Sabdar  *
23722654012fSReza Sabdar  * Returns:
23732654012fSReza Sabdar  *   list - array of character strings
23742654012fSReza Sabdar  */
23752654012fSReza Sabdar char **
23762654012fSReza Sabdar ndmpd_make_exc_list(void)
23772654012fSReza Sabdar {
23782654012fSReza Sabdar 	char *val, **cpp;
23792654012fSReza Sabdar 	int i, n;
23802654012fSReza Sabdar 
23812654012fSReza Sabdar 	n = sizeof (exls);
23822654012fSReza Sabdar 	if ((cpp = ndmp_malloc(n)) != NULL) {
23832654012fSReza Sabdar 		for (i = 0; exls[i] != NULL; i++)
23842654012fSReza Sabdar 			cpp[i] = exls[i];
23852654012fSReza Sabdar 
23862654012fSReza Sabdar 		/*
23872654012fSReza Sabdar 		 * If ndmpd_get_prop returns NULL, the array will be
23882654012fSReza Sabdar 		 * null-terminated.
23892654012fSReza Sabdar 		 */
23902654012fSReza Sabdar 		val = ndmpd_get_prop(NDMP_DEBUG_PATH);
23912654012fSReza Sabdar 		cpp[i] = val;
23922654012fSReza Sabdar 	}
23932654012fSReza Sabdar 
23942654012fSReza Sabdar 	return (cpp);
23952654012fSReza Sabdar }
23962654012fSReza Sabdar 
23972654012fSReza Sabdar 
23982654012fSReza Sabdar /*
23992654012fSReza Sabdar  * ndmp_get_bk_dir_ino
24002654012fSReza Sabdar  *
24012654012fSReza Sabdar  * Get the inode number of the backup directory
24022654012fSReza Sabdar  */
24032654012fSReza Sabdar int
24042654012fSReza Sabdar ndmp_get_bk_dir_ino(ndmp_lbr_params_t *nlp)
24052654012fSReza Sabdar {
24062654012fSReza Sabdar 	int rv;
24072654012fSReza Sabdar 	struct stat64 st;
24082654012fSReza Sabdar 
24092654012fSReza Sabdar 	if (stat64(nlp->nlp_backup_path, &st) != 0) {
24102654012fSReza Sabdar 		rv = -1;
24112654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Getting inode # of \"%s\"",
24122654012fSReza Sabdar 		    nlp->nlp_backup_path);
24132654012fSReza Sabdar 	} else {
24142654012fSReza Sabdar 		rv = 0;
24152654012fSReza Sabdar 		nlp->nlp_bkdirino = st.st_ino;
24162654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp_bkdirino: %lu",
24172654012fSReza Sabdar 		    (uint_t)nlp->nlp_bkdirino);
24182654012fSReza Sabdar 	}
24192654012fSReza Sabdar 
24202654012fSReza Sabdar 	return (rv);
24212654012fSReza Sabdar }
24222654012fSReza Sabdar 
24232654012fSReza Sabdar 
24242654012fSReza Sabdar /*
24252654012fSReza Sabdar  * ndmp_check_utf8magic
24262654012fSReza Sabdar  *
24272654012fSReza Sabdar  * Check if the magic string for exists in the tar header. This
24282654012fSReza Sabdar  * magic string (which also indicates that the file names are in
24292654012fSReza Sabdar  * UTF8 format) is used as a crest to indetify our own tapes.
24302654012fSReza Sabdar  * This checking is always done before all restores except DAR
24312654012fSReza Sabdar  * restores.
24322654012fSReza Sabdar  */
24332654012fSReza Sabdar boolean_t
24342654012fSReza Sabdar ndmp_check_utf8magic(tlm_cmd_t *cmd)
24352654012fSReza Sabdar {
24362654012fSReza Sabdar 	char *cp;
24372654012fSReza Sabdar 	int err, len, actual_size;
24382654012fSReza Sabdar 
24392654012fSReza Sabdar 	if (cmd == NULL) {
24402654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "cmd == NULL");
24412654012fSReza Sabdar 		return (FALSE);
24422654012fSReza Sabdar 	}
24432654012fSReza Sabdar 	if (cmd->tc_buffers == NULL) {
24442654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "cmd->tc_buffers == NULL");
24452654012fSReza Sabdar 		return (FALSE);
24462654012fSReza Sabdar 	}
24472654012fSReza Sabdar 
24482654012fSReza Sabdar 	/* wait until the first buffer gets full. */
24492654012fSReza Sabdar 	tlm_buffer_in_buf_wait(cmd->tc_buffers);
24502654012fSReza Sabdar 
24512654012fSReza Sabdar 	err = actual_size = 0;
24522654012fSReza Sabdar 	cp = tlm_get_read_buffer(RECORDSIZE, &err, cmd->tc_buffers,
24532654012fSReza Sabdar 	    &actual_size);
24542654012fSReza Sabdar 	if (cp == NULL) {
24552654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Can't read from buffers, err: %d", err);
24562654012fSReza Sabdar 		return (FALSE);
24572654012fSReza Sabdar 	}
24582654012fSReza Sabdar 	len = strlen(NDMPUTF8MAGIC);
24592654012fSReza Sabdar 	if (actual_size < len) {
24602654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Not enough data in the buffers");
24612654012fSReza Sabdar 		return (FALSE);
24622654012fSReza Sabdar 	}
24632654012fSReza Sabdar 
24642654012fSReza Sabdar 	return ((strncmp(cp, NDMPUTF8MAGIC, len) == 0) ? TRUE : FALSE);
24652654012fSReza Sabdar }
24662654012fSReza Sabdar 
24672654012fSReza Sabdar 
24682654012fSReza Sabdar /*
24692654012fSReza Sabdar  * ndmp_get_cur_bk_time
24702654012fSReza Sabdar  *
24712654012fSReza Sabdar  * Get the backup checkpoint time.
24722654012fSReza Sabdar  */
24732654012fSReza Sabdar int
24742654012fSReza Sabdar ndmp_get_cur_bk_time(ndmp_lbr_params_t *nlp, time_t *tp, char *jname)
24752654012fSReza Sabdar {
24762654012fSReza Sabdar 	int err;
24772654012fSReza Sabdar 
24782654012fSReza Sabdar 	if (!nlp || !nlp->nlp_backup_path || !tp) {
24792654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid argument");
24802654012fSReza Sabdar 		return (-1);
24812654012fSReza Sabdar 	}
24822654012fSReza Sabdar 
24832654012fSReza Sabdar 	if (!fs_is_chkpnt_enabled(nlp->nlp_backup_path)) {
24842654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Not a chkpnt volume %s",
24852654012fSReza Sabdar 		    nlp->nlp_backup_path);
24862654012fSReza Sabdar 		*tp = time(NULL);
24872654012fSReza Sabdar 		return (0);
24882654012fSReza Sabdar 	}
24892654012fSReza Sabdar 
24902654012fSReza Sabdar 	err = tlm_get_chkpnt_time(nlp->nlp_backup_path, !NLP_ISCHKPNTED(nlp),
24912654012fSReza Sabdar 	    tp, jname);
24922654012fSReza Sabdar 	if (err != 0) {
24932654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Can't checkpoint time");
24942654012fSReza Sabdar 	} else {
24952654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "%s", cctime(tp));
24962654012fSReza Sabdar 	}
24972654012fSReza Sabdar 
24982654012fSReza Sabdar 	return (err);
24992654012fSReza Sabdar }
25002654012fSReza Sabdar 
25012654012fSReza Sabdar 
25022654012fSReza Sabdar /*
25032654012fSReza Sabdar  * get_relative_path
25042654012fSReza Sabdar  */
25052654012fSReza Sabdar char *
25062654012fSReza Sabdar ndmp_get_relative_path(char *base, char *fullpath)
25072654012fSReza Sabdar {
25082654012fSReza Sabdar 	char *p = fullpath;
25092654012fSReza Sabdar 
25102654012fSReza Sabdar 	if (!base || !*base)
25112654012fSReza Sabdar 		return (fullpath);
25122654012fSReza Sabdar 
25132654012fSReza Sabdar 	while (*base) {
25142654012fSReza Sabdar 		if (*base != *p)
25152654012fSReza Sabdar 			break;
25162654012fSReza Sabdar 		p++; base++;
25172654012fSReza Sabdar 	}
25182654012fSReza Sabdar 
25192654012fSReza Sabdar 	if (*p == '/')
25202654012fSReza Sabdar 		p++;
25212654012fSReza Sabdar 
25222654012fSReza Sabdar 	return ((*base) ? fullpath : p);
25232654012fSReza Sabdar }
25242654012fSReza Sabdar 
25252654012fSReza Sabdar 
25262654012fSReza Sabdar /*
25272654012fSReza Sabdar  * ndmp_get_nlp
25282654012fSReza Sabdar  *
25292654012fSReza Sabdar  * Get NDMP local backup parameters
25302654012fSReza Sabdar  *
25312654012fSReza Sabdar  * Parameter:
25322654012fSReza Sabdar  *   session cooke
25332654012fSReza Sabdar  *
25342654012fSReza Sabdar  * Returns:
25352654012fSReza Sabdar  *   LBR structure
25362654012fSReza Sabdar  */
25372654012fSReza Sabdar ndmp_lbr_params_t *
25382654012fSReza Sabdar ndmp_get_nlp(void *cookie)
25392654012fSReza Sabdar {
25402654012fSReza Sabdar 	if (cookie == NULL)
25412654012fSReza Sabdar 		return (NULL);
25422654012fSReza Sabdar 
25432654012fSReza Sabdar 	return (((ndmpd_session_t *)cookie)->ns_ndmp_lbr_params);
25442654012fSReza Sabdar }
25452654012fSReza Sabdar 
25462654012fSReza Sabdar 
25472654012fSReza Sabdar /*
25482654012fSReza Sabdar  * is_tape_unit_ready
25492654012fSReza Sabdar  *
25502654012fSReza Sabdar  * Check if the tape device is ready or not
25512654012fSReza Sabdar  */
25522654012fSReza Sabdar boolean_t
25532654012fSReza Sabdar is_tape_unit_ready(char *adptnm, int dev_id)
25542654012fSReza Sabdar {
25552654012fSReza Sabdar 	int try;
25562654012fSReza Sabdar 	int fd = 0;
25572654012fSReza Sabdar 
25582654012fSReza Sabdar 	try = TUR_MAX_TRY;
2559295e611fSReza Sabdar 	if (dev_id <= 0) {
2560295e611fSReza Sabdar 		if ((fd = open(adptnm, O_RDONLY | O_NDELAY)) < 0)
2561295e611fSReza Sabdar 			return (FALSE);
2562295e611fSReza Sabdar 	} else {
25632654012fSReza Sabdar 		fd = dev_id;
2564295e611fSReza Sabdar 	}
25652654012fSReza Sabdar 	do {
25662654012fSReza Sabdar 		if (scsi_test_unit_ready(fd) >= 0) {
25672654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "Unit is ready");
25682654012fSReza Sabdar 
256986c48bbfSReza Sabdar 			if (dev_id <= 0)
25702654012fSReza Sabdar 				(void) close(fd);
25712654012fSReza Sabdar 
25722654012fSReza Sabdar 			return (TRUE);
25732654012fSReza Sabdar 		}
25742654012fSReza Sabdar 
25752654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Unit not ready");
25762654012fSReza Sabdar 		(void) usleep(TUR_WAIT);
25772654012fSReza Sabdar 
25782654012fSReza Sabdar 	} while (--try > 0);
25792654012fSReza Sabdar 
258086c48bbfSReza Sabdar 	if (dev_id <= 0)
25812654012fSReza Sabdar 		(void) close(fd);
25822654012fSReza Sabdar 
25832654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "Unit didn't get ready");
25842654012fSReza Sabdar 	return (FALSE);
25852654012fSReza Sabdar }
25862654012fSReza Sabdar 
25872654012fSReza Sabdar 
25882654012fSReza Sabdar /*
25892654012fSReza Sabdar  * scsi_test_unit_ready
25902654012fSReza Sabdar  *
25912654012fSReza Sabdar  * This is for Test Unit Read, without this function, the only
25922654012fSReza Sabdar  * impact is getting EBUSY's before each operation which we have
25932654012fSReza Sabdar  * busy waiting loops checking EBUSY error code.
25942654012fSReza Sabdar  */
25952654012fSReza Sabdar static int
25962654012fSReza Sabdar scsi_test_unit_ready(int dev_id)
25972654012fSReza Sabdar {
25982654012fSReza Sabdar 	struct uscsi_cmd ucmd;
25992654012fSReza Sabdar 	union scsi_cdb cdb;
26002654012fSReza Sabdar 	int retval;
26012654012fSReza Sabdar 
26022654012fSReza Sabdar 	(void) memset(&ucmd, 0, sizeof (struct uscsi_cmd));
26032654012fSReza Sabdar 	(void) memset(&cdb, 0, sizeof (union scsi_cdb));
26042654012fSReza Sabdar 	cdb.scc_cmd = SCMD_TEST_UNIT_READY;
26052654012fSReza Sabdar 	ucmd.uscsi_cdb = (caddr_t)&cdb;
26062654012fSReza Sabdar 	ucmd.uscsi_cdblen = CDB_GROUP0;
26072654012fSReza Sabdar 	ucmd.uscsi_flags |= USCSI_SILENT;
2608c211fc47SReza Sabdar 	ucmd.uscsi_timeout = 60;	/* Allow maximum 1 min */
26092654012fSReza Sabdar 
26102654012fSReza Sabdar 	retval = ioctl(dev_id, USCSICMD, &ucmd);
26112654012fSReza Sabdar 
26122654012fSReza Sabdar 	if (retval != 0 && errno != EIO) {
26132654012fSReza Sabdar 		NDMP_LOG(LOG_ERR,
26142654012fSReza Sabdar 		    "Failed to send inquiry request to device: %m.");
26152654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Inquiry request failed for"
26162654012fSReza Sabdar 		    " dev_id:%d err=%d -%m", dev_id, errno);
26172654012fSReza Sabdar 		retval = -errno;
26182654012fSReza Sabdar 	} else
26192654012fSReza Sabdar 		retval = -(ucmd.uscsi_status);
26202654012fSReza Sabdar 
26212654012fSReza Sabdar 	return (retval);
26222654012fSReza Sabdar }
26232654012fSReza Sabdar 
26242654012fSReza Sabdar 
26252654012fSReza Sabdar /*
26262654012fSReza Sabdar  * ndmp_load_params
26272654012fSReza Sabdar  *
26282654012fSReza Sabdar  * Load the parameters.
26292654012fSReza Sabdar  *
26302654012fSReza Sabdar  * Parameter:
26312654012fSReza Sabdar  *   void
26322654012fSReza Sabdar  *
26332654012fSReza Sabdar  * Returns:
26342654012fSReza Sabdar  *   void
26352654012fSReza Sabdar  */
26362654012fSReza Sabdar void
26372654012fSReza Sabdar ndmp_load_params(void)
26382654012fSReza Sabdar {
26392654012fSReza Sabdar 	ndmp_dump_path_node = ndmpd_get_prop_yorn(NDMP_DUMP_PATHNODE_ENV) ?
26402654012fSReza Sabdar 	    TRUE : FALSE;
26412654012fSReza Sabdar 	ndmp_tar_path_node = ndmpd_get_prop_yorn(NDMP_TAR_PATHNODE_ENV) ?
26422654012fSReza Sabdar 	    TRUE : FALSE;
26432654012fSReza Sabdar 	ndmp_ignore_ctime =
26442654012fSReza Sabdar 	    ndmpd_get_prop_yorn(NDMP_IGNCTIME_ENV) ? TRUE : FALSE;
26452654012fSReza Sabdar 	ndmp_include_lmtime = ndmpd_get_prop_yorn(NDMP_INCLMTIME_ENV) ?
26462654012fSReza Sabdar 	    TRUE : FALSE;
26472654012fSReza Sabdar 	ndmp_max_tok_seq = atoi(ndmpd_get_prop_default(NDMP_MAXSEQ_ENV, "9"));
26482654012fSReza Sabdar 
26492654012fSReza Sabdar 	ndmp_full_restore_path = ndmpd_get_prop_yorn(NDMP_FULL_RESTORE_PATH) ?
26502654012fSReza Sabdar 	    TRUE : FALSE;
26512654012fSReza Sabdar 
26522654012fSReza Sabdar 	ndmp_fhinode = ndmpd_get_prop_yorn(NDMP_FHIST_INCR_ENV) ? TRUE : FALSE;
26532654012fSReza Sabdar 
26542654012fSReza Sabdar 	/* Get the value from ndmp SMF property. */
26552654012fSReza Sabdar 	ndmp_dar_support = ndmpd_get_prop_yorn(NDMP_DAR_SUPPORT);
26562654012fSReza Sabdar 
26572654012fSReza Sabdar 	if ((ndmp_ver = atoi(ndmpd_get_prop(NDMP_VERSION_ENV))) == 0)
26582654012fSReza Sabdar 		ndmp_ver = NDMPVER;
26592654012fSReza Sabdar }
26602654012fSReza Sabdar 
26612654012fSReza Sabdar /*
26622654012fSReza Sabdar  * randomize
26632654012fSReza Sabdar  *
26642654012fSReza Sabdar  * Randomize the contents of a buffer
26652654012fSReza Sabdar  *
26662654012fSReza Sabdar  * Parameter:
26672654012fSReza Sabdar  *   buffer (output) - destination buffer
26682654012fSReza Sabdar  *   size (input) - buffer size
26692654012fSReza Sabdar  *
26702654012fSReza Sabdar  * Returns:
26712654012fSReza Sabdar  *   void
26722654012fSReza Sabdar  */
26732654012fSReza Sabdar void
26742654012fSReza Sabdar randomize(unsigned char *buffer, int size)
26752654012fSReza Sabdar {
26762654012fSReza Sabdar 	/* LINTED improper alignment */
26772654012fSReza Sabdar 	unsigned int *p = (unsigned int *)buffer;
26782654012fSReza Sabdar 	unsigned int dwlen = size / sizeof (unsigned int);
26792654012fSReza Sabdar 	unsigned int remlen = size % sizeof (unsigned int);
26802654012fSReza Sabdar 	unsigned int tmp;
26812654012fSReza Sabdar 	unsigned int i;
26822654012fSReza Sabdar 
26832654012fSReza Sabdar 	for (i = 0; i < dwlen; i++)
26842654012fSReza Sabdar 		*p++ = random();
26852654012fSReza Sabdar 
26862654012fSReza Sabdar 	if (remlen) {
26872654012fSReza Sabdar 		tmp = random();
26882654012fSReza Sabdar 		(void) memcpy(p, &tmp, remlen);
26892654012fSReza Sabdar 	}
26902654012fSReza Sabdar }
26912654012fSReza Sabdar 
26922654012fSReza Sabdar /*
26932654012fSReza Sabdar  * ndmpd_get_file_entry_type
26942654012fSReza Sabdar  *
26952654012fSReza Sabdar  * Converts the mode to the NDMP file type
26962654012fSReza Sabdar  *
26972654012fSReza Sabdar  * Parameter:
26982654012fSReza Sabdar  *   mode (input) - file mode
26992654012fSReza Sabdar  *   ftype (output) - file type
27002654012fSReza Sabdar  *
27012654012fSReza Sabdar  * Returns:
27022654012fSReza Sabdar  *   void
27032654012fSReza Sabdar  */
27042654012fSReza Sabdar void
27052654012fSReza Sabdar ndmpd_get_file_entry_type(int mode, ndmp_file_type *ftype)
27062654012fSReza Sabdar {
27072654012fSReza Sabdar 	switch (mode & S_IFMT) {
27082654012fSReza Sabdar 	case S_IFIFO:
27092654012fSReza Sabdar 		*ftype = NDMP_FILE_FIFO;
27102654012fSReza Sabdar 		break;
27112654012fSReza Sabdar 	case S_IFCHR:
27122654012fSReza Sabdar 		*ftype = NDMP_FILE_CSPEC;
27132654012fSReza Sabdar 		break;
27142654012fSReza Sabdar 	case S_IFDIR:
27152654012fSReza Sabdar 		*ftype = NDMP_FILE_DIR;
27162654012fSReza Sabdar 		break;
27172654012fSReza Sabdar 	case S_IFBLK:
27182654012fSReza Sabdar 		*ftype = NDMP_FILE_BSPEC;
27192654012fSReza Sabdar 		break;
27202654012fSReza Sabdar 	case S_IFREG:
27212654012fSReza Sabdar 		*ftype = NDMP_FILE_REG;
27222654012fSReza Sabdar 		break;
27232654012fSReza Sabdar 	case S_IFLNK:
27242654012fSReza Sabdar 		*ftype = NDMP_FILE_SLINK;
27252654012fSReza Sabdar 		break;
27262654012fSReza Sabdar 	default:
27272654012fSReza Sabdar 		*ftype = NDMP_FILE_SOCK;
27282654012fSReza Sabdar 		break;
27292654012fSReza Sabdar 	}
27302654012fSReza Sabdar }
27312654012fSReza Sabdar 
27322654012fSReza Sabdar /*
27332654012fSReza Sabdar  * Set a private data in the plugin context
27342654012fSReza Sabdar  */
27352654012fSReza Sabdar void
27362654012fSReza Sabdar ndmp_context_set_specific(ndmp_context_t *nctx, void *ptr)
27372654012fSReza Sabdar {
27382654012fSReza Sabdar 	nctx->nc_pldata = ptr;
27392654012fSReza Sabdar }
27402654012fSReza Sabdar 
27412654012fSReza Sabdar /*
27422654012fSReza Sabdar  * Get a private data in the plugin context
27432654012fSReza Sabdar  */
27442654012fSReza Sabdar void *
27452654012fSReza Sabdar ndmp_context_get_specific(ndmp_context_t *nctx)
27462654012fSReza Sabdar {
27472654012fSReza Sabdar 	return (nctx->nc_pldata);
27482654012fSReza Sabdar }
27498c4f9701SJanice Chang 
27508c4f9701SJanice Chang ndmpd_backup_type_t
27518c4f9701SJanice Chang ndmp_get_backup_type(ndmp_context_t *ctx)
27528c4f9701SJanice Chang {
27538c4f9701SJanice Chang 	ndmpd_session_t *session = (ndmpd_session_t *)ctx->nc_ddata;
27548c4f9701SJanice Chang 
27558c4f9701SJanice Chang 	return (session->ns_butype);
27568c4f9701SJanice Chang }
2757