xref: /titanic_52/usr/src/cmd/ndmpd/ndmp/ndmpd_data.c (revision 97f7c4750238e3c507904468e4e9f17b15a08e2d)
12654012fSReza Sabdar /*
28c4f9701SJanice Chang  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3*97f7c475SJan Kryl  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
42654012fSReza Sabdar  */
52654012fSReza Sabdar 
62654012fSReza Sabdar /*
72654012fSReza Sabdar  * BSD 3 Clause License
82654012fSReza Sabdar  *
92654012fSReza Sabdar  * Copyright (c) 2007, The Storage Networking Industry Association.
102654012fSReza Sabdar  *
112654012fSReza Sabdar  * Redistribution and use in source and binary forms, with or without
122654012fSReza Sabdar  * modification, are permitted provided that the following conditions
132654012fSReza Sabdar  * are met:
142654012fSReza Sabdar  * 	- Redistributions of source code must retain the above copyright
152654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer.
162654012fSReza Sabdar  *
172654012fSReza Sabdar  * 	- Redistributions in binary form must reproduce the above copyright
182654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer in
192654012fSReza Sabdar  *	  the documentation and/or other materials provided with the
202654012fSReza Sabdar  *	  distribution.
212654012fSReza Sabdar  *
222654012fSReza Sabdar  *	- Neither the name of The Storage Networking Industry Association (SNIA)
232654012fSReza Sabdar  *	  nor the names of its contributors may be used to endorse or promote
242654012fSReza Sabdar  *	  products derived from this software without specific prior written
252654012fSReza Sabdar  *	  permission.
262654012fSReza Sabdar  *
272654012fSReza Sabdar  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
282654012fSReza Sabdar  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
292654012fSReza Sabdar  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
302654012fSReza Sabdar  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
312654012fSReza Sabdar  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
322654012fSReza Sabdar  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
332654012fSReza Sabdar  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
342654012fSReza Sabdar  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
352654012fSReza Sabdar  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
362654012fSReza Sabdar  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
372654012fSReza Sabdar  * POSSIBILITY OF SUCH DAMAGE.
382654012fSReza Sabdar  */
392654012fSReza Sabdar /* Copyright (c) 2007, The Storage Networking Industry Association. */
402654012fSReza Sabdar /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
412654012fSReza Sabdar #include <sys/types.h>
422654012fSReza Sabdar #include <sys/param.h>
432654012fSReza Sabdar #include <sys/socket.h>
442654012fSReza Sabdar #include <netinet/in.h>
452654012fSReza Sabdar #include <errno.h>
462654012fSReza Sabdar #include <arpa/inet.h>
472654012fSReza Sabdar #include <stdlib.h>
482654012fSReza Sabdar #include <string.h>
492654012fSReza Sabdar #include "ndmpd_common.h"
502654012fSReza Sabdar #include "ndmpd.h"
512654012fSReza Sabdar 
522654012fSReza Sabdar static int ndmpd_data_error_send_v4(ndmpd_session_t *session,
532654012fSReza Sabdar     ndmp_data_halt_reason reason);
542654012fSReza Sabdar static int ndmpd_data_error_send(ndmpd_session_t *session,
552654012fSReza Sabdar     ndmp_data_halt_reason reason);
562654012fSReza Sabdar static void data_accept_connection_v3(void *cookie, int fd, ulong_t mode);
572654012fSReza Sabdar static int create_listen_socket_v3(ndmpd_session_t *session, ulong_t *addr,
582654012fSReza Sabdar     ushort_t *port);
592654012fSReza Sabdar static ndmp_error data_connect_sock_v3(ndmpd_session_t *session, ulong_t addr,
602654012fSReza Sabdar     ushort_t port);
612654012fSReza Sabdar static int discard_data_v3(ndmpd_session_t *session, ulong_t length);
622654012fSReza Sabdar static void nlp_release_job_stat(ndmpd_session_t *session);
632654012fSReza Sabdar static u_longlong_t ndmpd_data_get_info(ndmpd_session_t *session);
648c4f9701SJanice Chang 
658c4f9701SJanice Chang static ndmp_error ndmpd_tar_start_backup_v2(ndmpd_session_t *, char *,
668c4f9701SJanice Chang     ndmp_pval *, ulong_t);
678c4f9701SJanice Chang static ndmp_error ndmpd_tar_start_recover_v2(ndmpd_session_t *, char *,
688c4f9701SJanice Chang     ndmp_pval *, ulong_t, ndmp_name *, ulong_t);
698c4f9701SJanice Chang static ndmp_error ndmpd_tar_start_backup_v3(ndmpd_session_t *, char *,
708c4f9701SJanice Chang     ndmp_pval *, ulong_t);
718c4f9701SJanice Chang static ndmp_error ndmpd_tar_start_recover_v3(ndmpd_session_t *,
728c4f9701SJanice Chang     ndmp_pval *, ulong_t, ndmp_name_v3 *, ulong_t);
738c4f9701SJanice Chang 
748c4f9701SJanice Chang static ndmp_error ndmpd_zfs_start_op(ndmpd_session_t *,
758c4f9701SJanice Chang     ndmp_pval *, ulong_t, ndmp_name_v3 *, ulong_t, enum ndmp_data_operation);
762654012fSReza Sabdar 
772654012fSReza Sabdar 
782654012fSReza Sabdar /*
792654012fSReza Sabdar  * ************************************************************************
802654012fSReza Sabdar  * NDMP V2 HANDLERS
812654012fSReza Sabdar  * ************************************************************************
822654012fSReza Sabdar  */
832654012fSReza Sabdar 
842654012fSReza Sabdar /*
852654012fSReza Sabdar  * ndmpd_data_get_state_v2
862654012fSReza Sabdar  *
872654012fSReza Sabdar  * Request handler. Returns current data state.
882654012fSReza Sabdar  *
892654012fSReza Sabdar  * Parameters:
902654012fSReza Sabdar  *   connection (input) - connection handle.
912654012fSReza Sabdar  *   body       (input) - request message body.
922654012fSReza Sabdar  *
932654012fSReza Sabdar  * Returns:
942654012fSReza Sabdar  *   void
952654012fSReza Sabdar  */
962654012fSReza Sabdar /*ARGSUSED*/
972654012fSReza Sabdar void
982654012fSReza Sabdar ndmpd_data_get_state_v2(ndmp_connection_t *connection, void *body)
992654012fSReza Sabdar {
1002654012fSReza Sabdar 	ndmp_data_get_state_reply_v2 reply;
1012654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
1022654012fSReza Sabdar 
1032654012fSReza Sabdar 	reply.error = NDMP_NO_ERR;
1042654012fSReza Sabdar 	reply.operation = session->ns_data.dd_operation;
1052654012fSReza Sabdar 	reply.state = session->ns_data.dd_state;
1062654012fSReza Sabdar 	reply.halt_reason = session->ns_data.dd_halt_reason;
1072654012fSReza Sabdar 
1082654012fSReza Sabdar 	reply.est_time_remain =
1092654012fSReza Sabdar 	    session->ns_data.dd_module.dm_stats.ms_est_time_remaining;
1102654012fSReza Sabdar 	reply.est_bytes_remain =
1112654012fSReza Sabdar 	    long_long_to_quad(
1122654012fSReza Sabdar 	    session->ns_data.dd_module.dm_stats.ms_est_bytes_remaining);
1132654012fSReza Sabdar 
1142654012fSReza Sabdar 	reply.bytes_processed =
1152654012fSReza Sabdar 	    long_long_to_quad(ndmpd_data_get_info(session));
1162654012fSReza Sabdar 
1172654012fSReza Sabdar 	reply.mover = session->ns_data.dd_mover;
1182654012fSReza Sabdar 	reply.read_offset = long_long_to_quad(session->ns_data.dd_read_offset);
1192654012fSReza Sabdar 	reply.read_length = long_long_to_quad(session->ns_data.dd_read_length);
1202654012fSReza Sabdar 
1212654012fSReza Sabdar 	ndmp_send_reply(connection, &reply,
1222654012fSReza Sabdar 	    "sending data_get_state reply");
1232654012fSReza Sabdar }
1242654012fSReza Sabdar 
1252654012fSReza Sabdar 
1262654012fSReza Sabdar /*
1272654012fSReza Sabdar  * ndmpd_data_start_backup_v2
1282654012fSReza Sabdar  *
1292654012fSReza Sabdar  * Request handler. Starts a backup.
1302654012fSReza Sabdar  *
1312654012fSReza Sabdar  * Parameters:
1322654012fSReza Sabdar  *   connection (input) - connection handle.
1332654012fSReza Sabdar  *   body       (input) - request message body.
1342654012fSReza Sabdar  *
1352654012fSReza Sabdar  * Returns:
1362654012fSReza Sabdar  *   void
1372654012fSReza Sabdar  */
1382654012fSReza Sabdar void
1392654012fSReza Sabdar ndmpd_data_start_backup_v2(ndmp_connection_t *connection, void *body)
1402654012fSReza Sabdar {
1412654012fSReza Sabdar 	ndmp_data_start_backup_request_v2 *request;
1422654012fSReza Sabdar 	ndmp_data_start_backup_reply_v2 reply;
1432654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
1442654012fSReza Sabdar 	ndmp_error err;
1452654012fSReza Sabdar 
1462654012fSReza Sabdar 	request = (ndmp_data_start_backup_request_v2 *)body;
1472654012fSReza Sabdar 
1482654012fSReza Sabdar 	reply.error = NDMP_NO_ERR;
1492654012fSReza Sabdar 	session->ns_data.dd_mover = request->mover;
1502654012fSReza Sabdar 
1518c4f9701SJanice Chang 	err = ndmpd_tar_start_backup_v2(session, request->bu_type,
1528c4f9701SJanice Chang 	    request->env.env_val, request->env.env_len);
1532654012fSReza Sabdar 
1542654012fSReza Sabdar 	/*
1552654012fSReza Sabdar 	 * start_backup sends the reply if the backup is successfully started.
1562654012fSReza Sabdar 	 * Otherwise, send the reply containing the error here.
1572654012fSReza Sabdar 	 */
1582654012fSReza Sabdar 	if (err != NDMP_NO_ERR) {
1592654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "err: %d", err);
1602654012fSReza Sabdar 		reply.error = err;
1612654012fSReza Sabdar 		ndmp_send_reply(connection, &reply,
1622654012fSReza Sabdar 		    "sending data_start_backup reply");
1632654012fSReza Sabdar 		ndmpd_data_cleanup(session);
1642654012fSReza Sabdar 	}
1652654012fSReza Sabdar }
1662654012fSReza Sabdar 
1672654012fSReza Sabdar /*
1682654012fSReza Sabdar  * ndmpd_data_start_recover_v2
1692654012fSReza Sabdar  *
1702654012fSReza Sabdar  * Request handler. Starts a restore.
1712654012fSReza Sabdar  *
1722654012fSReza Sabdar  * Parameters:
1732654012fSReza Sabdar  *   connection (input) - connection handle.
1742654012fSReza Sabdar  *   body       (input) - request message body.
1752654012fSReza Sabdar  *
1762654012fSReza Sabdar  * Returns:
1772654012fSReza Sabdar  *   void
1782654012fSReza Sabdar  */
1792654012fSReza Sabdar void
1802654012fSReza Sabdar ndmpd_data_start_recover_v2(ndmp_connection_t *connection, void *body)
1812654012fSReza Sabdar {
1822654012fSReza Sabdar 	ndmp_data_start_recover_request_v2 *request;
1832654012fSReza Sabdar 	ndmp_data_start_recover_reply_v2 reply;
1842654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
1852654012fSReza Sabdar 	ndmp_error err;
1862654012fSReza Sabdar 
1872654012fSReza Sabdar 	request = (ndmp_data_start_recover_request_v2 *) body;
1882654012fSReza Sabdar 	session->ns_data.dd_mover = request->mover;
1892654012fSReza Sabdar 
1908c4f9701SJanice Chang 	err = ndmpd_tar_start_recover_v2(session, request->bu_type,
1918c4f9701SJanice Chang 	    request->env.env_val, request->env.env_len,
1928c4f9701SJanice Chang 	    request->nlist.nlist_val, request->nlist.nlist_len);
1938c4f9701SJanice Chang 
1942654012fSReza Sabdar 	/*
1952654012fSReza Sabdar 	 * start_recover sends the reply if the recover is successfully started.
1962654012fSReza Sabdar 	 * Otherwise, send the reply containing the error here.
1972654012fSReza Sabdar 	 */
1982654012fSReza Sabdar 	if (err != NDMP_NO_ERR) {
1992654012fSReza Sabdar 		reply.error = err;
2002654012fSReza Sabdar 		ndmp_send_reply(connection, &reply,
2012654012fSReza Sabdar 		    "sending ndmp_data_start_recover_request_v2 reply");
2022654012fSReza Sabdar 		ndmpd_data_cleanup(session);
2032654012fSReza Sabdar 	}
2042654012fSReza Sabdar }
2052654012fSReza Sabdar 
2062654012fSReza Sabdar /*
2072654012fSReza Sabdar  * ndmpd_data_get_env_v2
2082654012fSReza Sabdar  *
2092654012fSReza Sabdar  * Request handler. Returns the environment variable array sent
2102654012fSReza Sabdar  * with the backup request. This request may only be sent with
2112654012fSReza Sabdar  * a backup operation is in progress.
2122654012fSReza Sabdar  *
2132654012fSReza Sabdar  * Parameters:
2142654012fSReza Sabdar  *   connection (input) - connection handle.
2152654012fSReza Sabdar  *   body       (input) - request message body.
2162654012fSReza Sabdar  *
2172654012fSReza Sabdar  * Returns:
2182654012fSReza Sabdar  *   void
2192654012fSReza Sabdar  */
2202654012fSReza Sabdar /*ARGSUSED*/
2212654012fSReza Sabdar void
2222654012fSReza Sabdar ndmpd_data_get_env_v2(ndmp_connection_t *connection, void *body)
2232654012fSReza Sabdar {
2242654012fSReza Sabdar 	ndmp_data_get_env_reply reply;
2252654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
2262654012fSReza Sabdar 
2272654012fSReza Sabdar 	(void) memset((void*)&reply, 0, sizeof (reply));
2282654012fSReza Sabdar 	if (session->ns_data.dd_operation != NDMP_DATA_OP_BACKUP) {
2292654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Backup operation not active.");
2302654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_STATE_ERR;
2312654012fSReza Sabdar 		reply.env.env_len = 0;
2322654012fSReza Sabdar 	} else {
2332654012fSReza Sabdar 		reply.error = NDMP_NO_ERR;
2342654012fSReza Sabdar 		reply.env.env_len = session->ns_data.dd_env_len;
2352654012fSReza Sabdar 		reply.env.env_val = session->ns_data.dd_env;
2362654012fSReza Sabdar 	}
2372654012fSReza Sabdar 
2382654012fSReza Sabdar 	ndmp_send_reply(connection, &reply, "sending data_get_env reply");
2392654012fSReza Sabdar }
2402654012fSReza Sabdar 
2412654012fSReza Sabdar 
2422654012fSReza Sabdar /*
2432654012fSReza Sabdar  * ndmpd_data_stop_v2
2442654012fSReza Sabdar  *
2452654012fSReza Sabdar  * Request handler. Stops the current data operation.
2462654012fSReza Sabdar  *
2472654012fSReza Sabdar  * Parameters:
2482654012fSReza Sabdar  *   connection (input) - connection handle.
2492654012fSReza Sabdar  *   body       (input) - request message body.
2502654012fSReza Sabdar  *
2512654012fSReza Sabdar  * Returns:
2522654012fSReza Sabdar  *   void
2532654012fSReza Sabdar  */
2542654012fSReza Sabdar /*ARGSUSED*/
2552654012fSReza Sabdar void
2562654012fSReza Sabdar ndmpd_data_stop_v2(ndmp_connection_t *connection, void *body)
2572654012fSReza Sabdar {
2582654012fSReza Sabdar 	ndmp_data_stop_reply reply;
2592654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
2602654012fSReza Sabdar 
2612654012fSReza Sabdar 	if (session->ns_data.dd_state != NDMP_DATA_STATE_HALTED) {
2622654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Invalid state to process stop request.");
2632654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_STATE_ERR;
2642654012fSReza Sabdar 		ndmp_send_reply(connection, &reply,
2652654012fSReza Sabdar 		    "sending data_stop reply");
2662654012fSReza Sabdar 		return;
2672654012fSReza Sabdar 	}
2682654012fSReza Sabdar 	ndmp_waitfor_op(session);
2692654012fSReza Sabdar 	ndmpd_data_cleanup(session);
2702654012fSReza Sabdar 	ndmpd_file_history_cleanup(session, FALSE);
2712654012fSReza Sabdar 
2722654012fSReza Sabdar 	nlp_release_job_stat(session);
2732654012fSReza Sabdar 
2742654012fSReza Sabdar 	/* prepare for another data operation */
2752654012fSReza Sabdar 	(void) ndmpd_data_init(session);
2762654012fSReza Sabdar 	ndmpd_file_history_init(session);
2772654012fSReza Sabdar 
2782654012fSReza Sabdar 	reply.error = NDMP_NO_ERR;
2792654012fSReza Sabdar 	ndmp_send_reply(connection, &reply, "sending data_stop reply");
2802654012fSReza Sabdar }
2812654012fSReza Sabdar 
2822654012fSReza Sabdar 
2832654012fSReza Sabdar /*
2842654012fSReza Sabdar  * ndmpd_data_abort_v2
2852654012fSReza Sabdar  *
2862654012fSReza Sabdar  * Request handler. Aborts the current backup/restore. The operation
2872654012fSReza Sabdar  * state is not changed to the halted state until after the operation
2882654012fSReza Sabdar  * has actually been aborted and the notify_halt request has been sent.
2892654012fSReza Sabdar  *
2902654012fSReza Sabdar  * Parameters:
2912654012fSReza Sabdar  *   connection (input) - connection handle.
2922654012fSReza Sabdar  *   body       (input) - request message body.
2932654012fSReza Sabdar  *
2942654012fSReza Sabdar  * Returns:
2952654012fSReza Sabdar  *   void
2962654012fSReza Sabdar  */
2972654012fSReza Sabdar /*ARGSUSED*/
2982654012fSReza Sabdar void
2992654012fSReza Sabdar ndmpd_data_abort_v2(ndmp_connection_t *connection, void *body)
3002654012fSReza Sabdar {
3012654012fSReza Sabdar 	ndmp_data_abort_reply reply;
3022654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
3032654012fSReza Sabdar 
3042654012fSReza Sabdar 	if (session->ns_data.dd_state == NDMP_DATA_STATE_IDLE ||
3052654012fSReza Sabdar 	    session->ns_data.dd_state == NDMP_DATA_STATE_HALTED) {
3062654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Invalid state to process abort request.");
3072654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_STATE_ERR;
3082654012fSReza Sabdar 		ndmp_send_reply(connection, &reply,
3092654012fSReza Sabdar 		    "sending data_abort reply");
3102654012fSReza Sabdar 		return;
3112654012fSReza Sabdar 	}
3122654012fSReza Sabdar 	/*
3132654012fSReza Sabdar 	 * Don't go to HALTED state yet. Need to wait for data operation to
3142654012fSReza Sabdar 	 * abort. When this happens, ndmpd_done will get called and will
3152654012fSReza Sabdar 	 * perform the halt processing.
3162654012fSReza Sabdar 	 */
3172654012fSReza Sabdar 	session->ns_data.dd_abort = TRUE;
3182654012fSReza Sabdar 	(*session->ns_data.dd_module.dm_abort_func)(
3192654012fSReza Sabdar 	    session->ns_data.dd_module.dm_module_cookie);
3202654012fSReza Sabdar 
3212654012fSReza Sabdar 	reply.error = NDMP_NO_ERR;
3222654012fSReza Sabdar 	ndmp_send_reply(connection, &reply, "sending data_abort reply");
3232654012fSReza Sabdar }
3242654012fSReza Sabdar 
3252654012fSReza Sabdar /*
3262654012fSReza Sabdar  * ************************************************************************
3272654012fSReza Sabdar  * NDMP V3 HANDLERS
3282654012fSReza Sabdar  * ************************************************************************
3292654012fSReza Sabdar  */
3302654012fSReza Sabdar 
3312654012fSReza Sabdar /*
3322654012fSReza Sabdar  * ndmpd_data_get_state_v3
3332654012fSReza Sabdar  *
3342654012fSReza Sabdar  * Request handler. Returns current data state.
3352654012fSReza Sabdar  *
3362654012fSReza Sabdar  * Parameters:
3372654012fSReza Sabdar  *   connection (input) - connection handle.
3382654012fSReza Sabdar  *   body       (input) - request message body.
3392654012fSReza Sabdar  *
3402654012fSReza Sabdar  * Returns:
3412654012fSReza Sabdar  *   void
3422654012fSReza Sabdar  */
3432654012fSReza Sabdar /*ARGSUSED*/
3442654012fSReza Sabdar void
3452654012fSReza Sabdar ndmpd_data_get_state_v3(ndmp_connection_t *connection, void *body)
3462654012fSReza Sabdar {
3472654012fSReza Sabdar 	ndmp_data_get_state_reply_v3 reply;
3482654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
3492654012fSReza Sabdar 
3502654012fSReza Sabdar 	(void) memset((void*)&reply, 0, sizeof (reply));
3512654012fSReza Sabdar 
3522654012fSReza Sabdar 	reply.error = NDMP_NO_ERR;
3532654012fSReza Sabdar 	reply.invalid = NDMP_DATA_STATE_EST_BYTES_REMAIN_INVALID
3542654012fSReza Sabdar 	    | NDMP_DATA_STATE_EST_TIME_REMAIN_INVALID;
3552654012fSReza Sabdar 	reply.operation = session->ns_data.dd_operation;
3562654012fSReza Sabdar 	reply.state = session->ns_data.dd_state;
3572654012fSReza Sabdar 	reply.halt_reason = session->ns_data.dd_halt_reason;
3582654012fSReza Sabdar 
3592654012fSReza Sabdar 	if (reply.operation == NDMP_DATA_OP_BACKUP)
3602654012fSReza Sabdar 		reply.bytes_processed =
3612654012fSReza Sabdar 		    long_long_to_quad(
3622654012fSReza Sabdar 		    session->ns_data.dd_module.dm_stats.ms_bytes_processed);
3632654012fSReza Sabdar 	else
3642654012fSReza Sabdar 		reply.bytes_processed =
3652654012fSReza Sabdar 		    long_long_to_quad(ndmpd_data_get_info(session));
3662654012fSReza Sabdar 
3672654012fSReza Sabdar 	reply.est_bytes_remain = long_long_to_quad(0LL);
3682654012fSReza Sabdar 	reply.est_time_remain = 0;
3692654012fSReza Sabdar 	if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE)
3702654012fSReza Sabdar 		ndmp_copy_addr_v3(&reply.data_connection_addr,
3712654012fSReza Sabdar 		    &session->ns_data.dd_data_addr);
3722654012fSReza Sabdar 	reply.read_offset = long_long_to_quad(session->ns_data.dd_read_offset);
3732654012fSReza Sabdar 	reply.read_length = long_long_to_quad(session->ns_data.dd_read_length);
3742654012fSReza Sabdar 
3752654012fSReza Sabdar 	ndmp_send_reply(connection, &reply,
3762654012fSReza Sabdar 	    "sending ndmp_data_get_state_v3 reply");
3772654012fSReza Sabdar }
3782654012fSReza Sabdar 
3792654012fSReza Sabdar 
3802654012fSReza Sabdar /*
3812654012fSReza Sabdar  * ndmpd_data_start_backup_v3
3822654012fSReza Sabdar  *
3832654012fSReza Sabdar  * Request handler. Starts a backup.
3842654012fSReza Sabdar  *
3852654012fSReza Sabdar  * Parameters:
3862654012fSReza Sabdar  *   connection (input) - connection handle.
3872654012fSReza Sabdar  *   body       (input) - request message body.
3882654012fSReza Sabdar  *
3892654012fSReza Sabdar  * Returns:
3902654012fSReza Sabdar  *   void
3912654012fSReza Sabdar  */
3922654012fSReza Sabdar void
3932654012fSReza Sabdar ndmpd_data_start_backup_v3(ndmp_connection_t *connection, void *body)
3942654012fSReza Sabdar {
3952654012fSReza Sabdar 	ndmp_data_start_backup_request_v3 *request;
3962654012fSReza Sabdar 	ndmp_data_start_backup_reply_v3 reply;
3972654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
3982654012fSReza Sabdar 
3992654012fSReza Sabdar 	request = (ndmp_data_start_backup_request_v3 *)body;
4002654012fSReza Sabdar 
4012654012fSReza Sabdar 	(void) memset((void*)&reply, 0, sizeof (reply));
4022654012fSReza Sabdar 
4038c4f9701SJanice Chang 	if (session->ns_data.dd_state != NDMP_DATA_STATE_CONNECTED) {
4048c4f9701SJanice Chang 		NDMP_LOG(LOG_ERR,
4058c4f9701SJanice Chang 		    "Can't start new backup in current state.");
4068c4f9701SJanice Chang 		NDMP_LOG(LOG_ERR,
4078c4f9701SJanice Chang 		    "Connection to the mover is not established.");
4088c4f9701SJanice Chang 		reply.error = NDMP_ILLEGAL_STATE_ERR;
4098c4f9701SJanice Chang 		goto _error;
4108c4f9701SJanice Chang 	}
4118c4f9701SJanice Chang 
4128c4f9701SJanice Chang 	if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_LOCAL) {
4138c4f9701SJanice Chang 		if (session->ns_tape.td_mode == NDMP_TAPE_READ_MODE) {
4148c4f9701SJanice Chang 			NDMP_LOG(LOG_ERR, "Write protected device.");
4158c4f9701SJanice Chang 			reply.error = NDMP_WRITE_PROTECT_ERR;
4168c4f9701SJanice Chang 			goto _error;
4178c4f9701SJanice Chang 		}
4188c4f9701SJanice Chang 	}
4198c4f9701SJanice Chang 
4208c4f9701SJanice Chang 	if (strcasecmp(request->bu_type, NDMP_TAR_TYPE) == 0) {
4218c4f9701SJanice Chang 		session->ns_butype = NDMP_BUTYPE_TAR;
4228c4f9701SJanice Chang 	} else if (strcasecmp(request->bu_type, NDMP_DUMP_TYPE) == 0) {
4238c4f9701SJanice Chang 		session->ns_butype = NDMP_BUTYPE_DUMP;
4248c4f9701SJanice Chang 	} else if (strcasecmp(request->bu_type, NDMP_ZFS_TYPE) == 0) {
4258c4f9701SJanice Chang 		session->ns_butype = NDMP_BUTYPE_ZFS;
4268c4f9701SJanice Chang 	} else {
4278c4f9701SJanice Chang 		char msg_invalid[32];
4288c4f9701SJanice Chang 		char msg_types[32];
4298c4f9701SJanice Chang 
4308c4f9701SJanice Chang 		(void) snprintf(msg_invalid, 32, "Invalid backup type: %s.",
4318c4f9701SJanice Chang 		    request->bu_type);
4328c4f9701SJanice Chang 		(void) snprintf(msg_types, 32,
4338c4f9701SJanice Chang 		    "Supported backup types are tar, dump, and zfs.");
4348c4f9701SJanice Chang 
4358c4f9701SJanice Chang 		NDMP_APILOG((void *) session, NDMP_LOG_ERROR, ++ndmp_log_msg_id,
4368c4f9701SJanice Chang 		    msg_invalid);
4378c4f9701SJanice Chang 		NDMP_APILOG((void *) session, NDMP_LOG_ERROR, ++ndmp_log_msg_id,
4388c4f9701SJanice Chang 		    msg_types);
4398c4f9701SJanice Chang 		NDMP_LOG(LOG_ERR, msg_invalid);
4408c4f9701SJanice Chang 		NDMP_LOG(LOG_ERR, msg_types);
4418c4f9701SJanice Chang 
4428c4f9701SJanice Chang 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
4438c4f9701SJanice Chang 		goto _error;
4448c4f9701SJanice Chang 	}
4458c4f9701SJanice Chang 
4468c4f9701SJanice Chang 	if (session->ns_butype == NDMP_BUTYPE_ZFS) {
4478c4f9701SJanice Chang 		reply.error = ndmpd_zfs_start_op(session, request->env.env_val,
4488c4f9701SJanice Chang 		    request->env.env_len, NULL, 0, NDMP_DATA_OP_BACKUP);
4498c4f9701SJanice Chang 	} else {
4508c4f9701SJanice Chang 		reply.error = ndmpd_tar_start_backup_v3(session,
4518c4f9701SJanice Chang 		    request->bu_type, request->env.env_val,
4522654012fSReza Sabdar 		    request->env.env_len);
4538c4f9701SJanice Chang 	}
4542654012fSReza Sabdar 
4552654012fSReza Sabdar 	/*
4568c4f9701SJanice Chang 	 * *_start_backup* sends the reply if the backup is
4572654012fSReza Sabdar 	 * successfully started.  Otherwise, send the reply
4582654012fSReza Sabdar 	 * containing the error here.
4592654012fSReza Sabdar 	 */
4608c4f9701SJanice Chang 
4618c4f9701SJanice Chang _error:
4628c4f9701SJanice Chang 
4638c4f9701SJanice Chang 	if (reply.error != NDMP_NO_ERR) {
4642654012fSReza Sabdar 		ndmp_send_reply(connection, &reply,
4652654012fSReza Sabdar 		    "sending data_start_backup_v3 reply");
4662654012fSReza Sabdar 		ndmpd_data_cleanup(session);
4672654012fSReza Sabdar 	}
4682654012fSReza Sabdar }
4692654012fSReza Sabdar 
4702654012fSReza Sabdar /*
4712654012fSReza Sabdar  * ndmpd_data_start_recover_v3
4722654012fSReza Sabdar  *
4732654012fSReza Sabdar  * Request handler. Starts a restore.
4742654012fSReza Sabdar  *
4752654012fSReza Sabdar  * Parameters:
4762654012fSReza Sabdar  *   connection (input) - connection handle.
4772654012fSReza Sabdar  *   body       (input) - request message body.
4782654012fSReza Sabdar  *
4792654012fSReza Sabdar  * Returns:
4802654012fSReza Sabdar  *   void
4812654012fSReza Sabdar  */
4822654012fSReza Sabdar void
4832654012fSReza Sabdar ndmpd_data_start_recover_v3(ndmp_connection_t *connection, void *body)
4842654012fSReza Sabdar {
4852654012fSReza Sabdar 	ndmp_data_start_recover_request_v3 *request;
4862654012fSReza Sabdar 	ndmp_data_start_recover_reply_v3 reply;
4872654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
4882654012fSReza Sabdar 
4892654012fSReza Sabdar 	request = (ndmp_data_start_recover_request_v3 *)body;
4902654012fSReza Sabdar 
4912654012fSReza Sabdar 	(void) memset((void*)&reply, 0, sizeof (reply));
4922654012fSReza Sabdar 
4938c4f9701SJanice Chang 	if (session->ns_data.dd_state != NDMP_DATA_STATE_CONNECTED) {
4948c4f9701SJanice Chang 		NDMP_LOG(LOG_ERR, "Can't start new recover in current state.");
4958c4f9701SJanice Chang 		reply.error = NDMP_ILLEGAL_STATE_ERR;
4968c4f9701SJanice Chang 		goto _error;
4978c4f9701SJanice Chang 	}
4988c4f9701SJanice Chang 
4998c4f9701SJanice Chang 	if (strcasecmp(request->bu_type, NDMP_TAR_TYPE) == 0) {
5008c4f9701SJanice Chang 		session->ns_butype = NDMP_BUTYPE_TAR;
5018c4f9701SJanice Chang 	} else if (strcasecmp(request->bu_type, NDMP_DUMP_TYPE) == 0) {
5028c4f9701SJanice Chang 		session->ns_butype = NDMP_BUTYPE_DUMP;
5038c4f9701SJanice Chang 	} else if (strcasecmp(request->bu_type, NDMP_ZFS_TYPE) == 0) {
5048c4f9701SJanice Chang 		session->ns_butype = NDMP_BUTYPE_ZFS;
5058c4f9701SJanice Chang 	} else {
5068c4f9701SJanice Chang 		char msg_invalid[32];
5078c4f9701SJanice Chang 		char msg_types[32];
5088c4f9701SJanice Chang 
5098c4f9701SJanice Chang 		(void) snprintf(msg_invalid, 32, "Invalid backup type: %s.",
5108c4f9701SJanice Chang 		    request->bu_type);
5118c4f9701SJanice Chang 		(void) snprintf(msg_types, 32,
5128c4f9701SJanice Chang 		    "Supported backup types are tar, dump, and zfs.");
5138c4f9701SJanice Chang 
5148c4f9701SJanice Chang 		NDMP_APILOG((void *) session, NDMP_LOG_ERROR, ++ndmp_log_msg_id,
5158c4f9701SJanice Chang 		    msg_invalid);
5168c4f9701SJanice Chang 		NDMP_APILOG((void *) session, NDMP_LOG_ERROR, ++ndmp_log_msg_id,
5178c4f9701SJanice Chang 		    msg_types);
5188c4f9701SJanice Chang 		NDMP_LOG(LOG_ERR, msg_invalid);
5198c4f9701SJanice Chang 		NDMP_LOG(LOG_ERR, msg_types);
5208c4f9701SJanice Chang 
5218c4f9701SJanice Chang 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
5228c4f9701SJanice Chang 		goto _error;
5238c4f9701SJanice Chang 	}
5248c4f9701SJanice Chang 
5258c4f9701SJanice Chang 	if (session->ns_butype == NDMP_BUTYPE_ZFS) {
5268c4f9701SJanice Chang 		reply.error = ndmpd_zfs_start_op(session, request->env.env_val,
5272654012fSReza Sabdar 		    request->env.env_len, request->nlist.nlist_val,
5288c4f9701SJanice Chang 		    request->nlist.nlist_len, NDMP_DATA_OP_RECOVER);
5298c4f9701SJanice Chang 	} else {
5308c4f9701SJanice Chang 		reply.error = ndmpd_tar_start_recover_v3(session,
5318c4f9701SJanice Chang 		    request->env.env_val, request->env.env_len,
5328c4f9701SJanice Chang 		    request->nlist.nlist_val, request->nlist.nlist_len);
5338c4f9701SJanice Chang 	}
5342654012fSReza Sabdar 
5352654012fSReza Sabdar 	/*
5368c4f9701SJanice Chang 	 * *_start_recover* sends the reply if the recover is
5372654012fSReza Sabdar 	 * successfully started.  Otherwise, send the reply
5382654012fSReza Sabdar 	 * containing the error here.
5392654012fSReza Sabdar 	 */
5408c4f9701SJanice Chang 
5418c4f9701SJanice Chang _error:
5428c4f9701SJanice Chang 
5438c4f9701SJanice Chang 	if (reply.error != NDMP_NO_ERR) {
5442654012fSReza Sabdar 		ndmp_send_reply(connection, &reply,
5452654012fSReza Sabdar 		    "sending data_start_recover_v3 reply");
5462654012fSReza Sabdar 		ndmpd_data_error(session, NDMP_DATA_HALT_INTERNAL_ERROR);
5472654012fSReza Sabdar 		ndmpd_data_cleanup(session);
5482654012fSReza Sabdar 	}
5492654012fSReza Sabdar }
5502654012fSReza Sabdar 
5512654012fSReza Sabdar /*
5522654012fSReza Sabdar  * ndmpd_data_abort_v3
5532654012fSReza Sabdar  *
5542654012fSReza Sabdar  * Request handler. Aborts the current backup/restore. The operation
5552654012fSReza Sabdar  * state is not changed to the halted state until after the operation
5562654012fSReza Sabdar  * has actually been aborted and the notify_halt request has been sent.
5572654012fSReza Sabdar  *
5582654012fSReza Sabdar  * Parameters:
5592654012fSReza Sabdar  *   connection (input) - connection handle.
5602654012fSReza Sabdar  *   body       (input) - request message body.
5612654012fSReza Sabdar  *
5622654012fSReza Sabdar  * Returns:
5632654012fSReza Sabdar  *   void
5642654012fSReza Sabdar  */
5652654012fSReza Sabdar /*ARGSUSED*/
5662654012fSReza Sabdar void
5672654012fSReza Sabdar ndmpd_data_abort_v3(ndmp_connection_t *connection, void *body)
5682654012fSReza Sabdar {
5692654012fSReza Sabdar 	ndmp_data_abort_reply reply;
5702654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
5712654012fSReza Sabdar 
5722654012fSReza Sabdar 	switch (session->ns_data.dd_state) {
5732654012fSReza Sabdar 	case NDMP_DATA_STATE_IDLE:
5742654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_STATE_ERR;
5752654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Invalid state to process abort request.");
5762654012fSReza Sabdar 		break;
5772654012fSReza Sabdar 
5782654012fSReza Sabdar 	case NDMP_DATA_STATE_ACTIVE:
5792654012fSReza Sabdar 		/*
5802654012fSReza Sabdar 		 * Don't go to HALTED state yet.  Need to wait for data
5812654012fSReza Sabdar 		 * operation to abort.  When this happens, ndmpd_done_v3
5822654012fSReza Sabdar 		 * will get called and will perform the halt processing.
5832654012fSReza Sabdar 		 */
5842654012fSReza Sabdar 		reply.error = NDMP_NO_ERR;
5852654012fSReza Sabdar 		session->ns_data.dd_abort = TRUE;
5862654012fSReza Sabdar 		if (session->ns_data.dd_module.dm_abort_func)
5872654012fSReza Sabdar 			(*session->ns_data.dd_module.dm_abort_func)(
5882654012fSReza Sabdar 			    session->ns_data.dd_module.dm_module_cookie);
5892654012fSReza Sabdar 		break;
5902654012fSReza Sabdar 
5912654012fSReza Sabdar 	case NDMP_DATA_STATE_HALTED:
5922654012fSReza Sabdar 	case NDMP_DATA_STATE_LISTEN:
5932654012fSReza Sabdar 	case NDMP_DATA_STATE_CONNECTED:
5942654012fSReza Sabdar 		reply.error = NDMP_NO_ERR;
5952654012fSReza Sabdar 		session->ns_data.dd_abort = TRUE;
5962654012fSReza Sabdar 		ndmpd_data_error(session, NDMP_DATA_HALT_ABORTED);
5972654012fSReza Sabdar 		break;
5982654012fSReza Sabdar 	default:
5992654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_STATE_ERR;
6002654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Unknown data V3 state %d",
6012654012fSReza Sabdar 		    session->ns_data.dd_state);
6022654012fSReza Sabdar 	}
6032654012fSReza Sabdar 
6042654012fSReza Sabdar 	ndmp_send_reply(connection, &reply,
6052654012fSReza Sabdar 	    "sending data_abort_v3 reply");
6062654012fSReza Sabdar }
6072654012fSReza Sabdar 
6082654012fSReza Sabdar 
6092654012fSReza Sabdar /*
6102654012fSReza Sabdar  * ndmpd_data_stop_v3
6112654012fSReza Sabdar  *
6122654012fSReza Sabdar  * Request handler. Stops the current data operation.
6132654012fSReza Sabdar  *
6142654012fSReza Sabdar  * Parameters:
6152654012fSReza Sabdar  *   connection (input) - connection handle.
6162654012fSReza Sabdar  *   body       (input) - request message body.
6172654012fSReza Sabdar  *
6182654012fSReza Sabdar  * Returns:
6192654012fSReza Sabdar  *   void
6202654012fSReza Sabdar  */
6212654012fSReza Sabdar /*ARGSUSED*/
6222654012fSReza Sabdar void
6232654012fSReza Sabdar ndmpd_data_stop_v3(ndmp_connection_t *connection, void *body)
6242654012fSReza Sabdar {
6252654012fSReza Sabdar 	ndmp_data_stop_reply reply;
6262654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
6272654012fSReza Sabdar 
6282654012fSReza Sabdar 	if (session->ns_data.dd_state != NDMP_DATA_STATE_HALTED) {
6292654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Invalid state to process stop request.");
6302654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_STATE_ERR;
6312654012fSReza Sabdar 		ndmp_send_reply(connection, &reply,
6322654012fSReza Sabdar 		    "sending data_stop_v3 reply");
6332654012fSReza Sabdar 		return;
6342654012fSReza Sabdar 	}
6352654012fSReza Sabdar 	ndmp_waitfor_op(session);
6362654012fSReza Sabdar 	ndmpd_data_cleanup(session);
6372654012fSReza Sabdar 	ndmpd_file_history_cleanup(session, FALSE);
6382654012fSReza Sabdar 
6392654012fSReza Sabdar 	/* prepare for another data operation */
6402654012fSReza Sabdar 	(void) ndmpd_data_init(session);
6412654012fSReza Sabdar 	ndmpd_file_history_init(session);
6422654012fSReza Sabdar 
6432654012fSReza Sabdar 	reply.error = NDMP_NO_ERR;
6442654012fSReza Sabdar 	ndmp_send_reply(connection, &reply,
6452654012fSReza Sabdar 	    "sending data_stop_v3 reply");
6462654012fSReza Sabdar }
6472654012fSReza Sabdar 
6482654012fSReza Sabdar 
6492654012fSReza Sabdar /*
6502654012fSReza Sabdar  * ndmpd_data_listen_v3
6512654012fSReza Sabdar  *
6522654012fSReza Sabdar  * Request handler. Configures the server to listen for a connection
6532654012fSReza Sabdar  * from a remote mover.
6542654012fSReza Sabdar  *
6552654012fSReza Sabdar  * Parameters:
6562654012fSReza Sabdar  *   connection (input) - connection handle.
6572654012fSReza Sabdar  *   body       (input) - request message body.
6582654012fSReza Sabdar  *
6592654012fSReza Sabdar  * Returns:
6602654012fSReza Sabdar  *   void
6612654012fSReza Sabdar  */
6622654012fSReza Sabdar void
6632654012fSReza Sabdar ndmpd_data_listen_v3(ndmp_connection_t *connection, void *body)
6642654012fSReza Sabdar {
6652654012fSReza Sabdar 	ndmp_data_listen_request_v3 *request;
6662654012fSReza Sabdar 	ndmp_data_listen_reply_v3 reply;
6672654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
6682654012fSReza Sabdar 	ulong_t addr;
6692654012fSReza Sabdar 	ushort_t port;
6702654012fSReza Sabdar 
6712654012fSReza Sabdar 	request = (ndmp_data_listen_request_v3 *)body;
6722654012fSReza Sabdar 
6732654012fSReza Sabdar 	(void) memset((void*)&reply, 0, sizeof (reply));
6742654012fSReza Sabdar 
6752654012fSReza Sabdar 	if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
6762654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_STATE_ERR;
6772654012fSReza Sabdar 		NDMP_LOG(LOG_ERR,
6782654012fSReza Sabdar 		    "Invalid internal data state to process listen request.");
6792654012fSReza Sabdar 	} else if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) {
6802654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_STATE_ERR;
6812654012fSReza Sabdar 		NDMP_LOG(LOG_ERR,
6822654012fSReza Sabdar 		    "Invalid mover state to process listen request.");
6832654012fSReza Sabdar 	} else {
6842654012fSReza Sabdar 		reply.error = NDMP_NO_ERR;
6852654012fSReza Sabdar 	}
6862654012fSReza Sabdar 
6872654012fSReza Sabdar 	if (reply.error != NDMP_NO_ERR) {
6882654012fSReza Sabdar 		ndmp_send_reply(connection, &reply,
6892654012fSReza Sabdar 		    "ndmp_data_listen_request_v3 reply");
6902654012fSReza Sabdar 		return;
6912654012fSReza Sabdar 	}
6922654012fSReza Sabdar 
6932654012fSReza Sabdar 	switch (request->addr_type) {
6942654012fSReza Sabdar 	case NDMP_ADDR_LOCAL:
6952654012fSReza Sabdar 		reply.data_connection_addr.addr_type = request->addr_type;
6962654012fSReza Sabdar 		session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_LOCAL;
6972654012fSReza Sabdar 		break;
6982654012fSReza Sabdar 	case NDMP_ADDR_TCP:
6992654012fSReza Sabdar 		if (create_listen_socket_v3(session, &addr, &port) < 0) {
7002654012fSReza Sabdar 			reply.error = NDMP_IO_ERR;
7012654012fSReza Sabdar 			break;
7022654012fSReza Sabdar 		}
7032654012fSReza Sabdar 
7042654012fSReza Sabdar 		reply.error = NDMP_NO_ERR;
7052654012fSReza Sabdar 		reply.data_connection_addr.addr_type = request->addr_type;
7062654012fSReza Sabdar 		reply.data_connection_addr.tcp_ip_v3 = htonl(addr);
7072654012fSReza Sabdar 		reply.data_connection_addr.tcp_port_v3 = htons(port);
7082654012fSReza Sabdar 		session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_TCP;
7092654012fSReza Sabdar 		session->ns_data.dd_data_addr.tcp_ip_v3 = addr;
7102654012fSReza Sabdar 		session->ns_data.dd_data_addr.tcp_port_v3 = ntohs(port);
7112654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "listen_socket: %d",
7122654012fSReza Sabdar 		    session->ns_data.dd_listen_sock);
7132654012fSReza Sabdar 		break;
7142654012fSReza Sabdar 
7152654012fSReza Sabdar 	default:
7162654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid address type: %d",
7172654012fSReza Sabdar 		    request->addr_type);
7182654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
7192654012fSReza Sabdar 		break;
7202654012fSReza Sabdar 	}
7212654012fSReza Sabdar 
7222654012fSReza Sabdar 	if (reply.error == NDMP_NO_ERR)
7232654012fSReza Sabdar 		session->ns_data.dd_state = NDMP_DATA_STATE_LISTEN;
7242654012fSReza Sabdar 
7252654012fSReza Sabdar 	ndmp_send_reply(connection, &reply,
7262654012fSReza Sabdar 	    "ndmp_data_listen_request_v3 reply");
7272654012fSReza Sabdar }
7282654012fSReza Sabdar 
7292654012fSReza Sabdar 
7302654012fSReza Sabdar /*
7312654012fSReza Sabdar  * ndmpd_data_connect_v3
7322654012fSReza Sabdar  *
7332654012fSReza Sabdar  * Request handler. Connects the data server to either a local
7342654012fSReza Sabdar  * or remote mover.
7352654012fSReza Sabdar  *
7362654012fSReza Sabdar  * Parameters:
7372654012fSReza Sabdar  *   connection (input) - connection handle.
7382654012fSReza Sabdar  *   body       (input) - request message body.
7392654012fSReza Sabdar  *
7402654012fSReza Sabdar  * Returns:
7412654012fSReza Sabdar  *   void
7422654012fSReza Sabdar  */
7432654012fSReza Sabdar void
7442654012fSReza Sabdar ndmpd_data_connect_v3(ndmp_connection_t *connection, void *body)
7452654012fSReza Sabdar {
7462654012fSReza Sabdar 	ndmp_data_connect_request_v3 *request;
7472654012fSReza Sabdar 	ndmp_data_connect_reply_v3 reply;
7482654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
7492654012fSReza Sabdar 
7502654012fSReza Sabdar 	request = (ndmp_data_connect_request_v3 *)body;
7512654012fSReza Sabdar 
7522654012fSReza Sabdar 	(void) memset((void*)&reply, 0, sizeof (reply));
7532654012fSReza Sabdar 
7542654012fSReza Sabdar 	if (!ndmp_valid_v3addr_type(request->addr.addr_type)) {
7552654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
7562654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid address type %d",
7572654012fSReza Sabdar 		    request->addr.addr_type);
7582654012fSReza Sabdar 	} else if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
7592654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_STATE_ERR;
7602654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Invalid state to process connect request.");
7612654012fSReza Sabdar 	} else {
7622654012fSReza Sabdar 		reply.error = NDMP_NO_ERR;
7632654012fSReza Sabdar 	}
7642654012fSReza Sabdar 
7652654012fSReza Sabdar 	if (reply.error != NDMP_NO_ERR) {
7662654012fSReza Sabdar 		ndmp_send_reply(connection, &reply,
7672654012fSReza Sabdar 		    "sending ndmp_data_connect_v3 reply");
7682654012fSReza Sabdar 		return;
7692654012fSReza Sabdar 	}
7702654012fSReza Sabdar 
7712654012fSReza Sabdar 	switch (request->addr.addr_type) {
7722654012fSReza Sabdar 	case NDMP_ADDR_LOCAL:
7732654012fSReza Sabdar 		/*
7742654012fSReza Sabdar 		 * Verify that the mover is listening for a
7752654012fSReza Sabdar 		 * local connection
7762654012fSReza Sabdar 		 */
7772654012fSReza Sabdar 		if (session->ns_mover.md_state != NDMP_MOVER_STATE_LISTEN ||
7782654012fSReza Sabdar 		    session->ns_mover.md_listen_sock != -1) {
7792654012fSReza Sabdar 			reply.error = NDMP_ILLEGAL_STATE_ERR;
7802654012fSReza Sabdar 			NDMP_LOG(LOG_ERR,
7812654012fSReza Sabdar 			    "Mover is not in local listen state.");
7822654012fSReza Sabdar 		} else {
7832654012fSReza Sabdar 			session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE;
7842654012fSReza Sabdar 		}
7852654012fSReza Sabdar 		break;
7862654012fSReza Sabdar 
7872654012fSReza Sabdar 	case NDMP_ADDR_TCP:
7882654012fSReza Sabdar 		reply.error = data_connect_sock_v3(session,
7892654012fSReza Sabdar 		    request->addr.tcp_ip_v3, request->addr.tcp_port_v3);
7902654012fSReza Sabdar 		break;
7912654012fSReza Sabdar 
7922654012fSReza Sabdar 	default:
7932654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
7942654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid address type %d",
7952654012fSReza Sabdar 		    request->addr.addr_type);
7962654012fSReza Sabdar 	}
7972654012fSReza Sabdar 
7982654012fSReza Sabdar 	if (reply.error == NDMP_NO_ERR)
7992654012fSReza Sabdar 		session->ns_data.dd_state = NDMP_DATA_STATE_CONNECTED;
8002654012fSReza Sabdar 
8012654012fSReza Sabdar 	ndmp_send_reply(connection, &reply,
8022654012fSReza Sabdar 	    "sending ndmp_data_connect_v3 reply");
8032654012fSReza Sabdar }
8042654012fSReza Sabdar 
8052654012fSReza Sabdar 
8062654012fSReza Sabdar /*
8072654012fSReza Sabdar  * ************************************************************************
8082654012fSReza Sabdar  * NDMP V4 HANDLERS
8092654012fSReza Sabdar  * ************************************************************************
8102654012fSReza Sabdar  */
8112654012fSReza Sabdar 
8122654012fSReza Sabdar /*
8132654012fSReza Sabdar  * ndmpd_data_get_env_v4
8142654012fSReza Sabdar  *
8152654012fSReza Sabdar  * Request handler. Returns the environment variable array sent
8162654012fSReza Sabdar  * with the backup request. This request may only be sent with
8172654012fSReza Sabdar  * a backup operation is in progress.
8182654012fSReza Sabdar  *
8192654012fSReza Sabdar  * Parameters:
8202654012fSReza Sabdar  *   connection (input) - connection handle.
8212654012fSReza Sabdar  *   body       (input) - request message body.
8222654012fSReza Sabdar  *
8232654012fSReza Sabdar  * Returns:
8242654012fSReza Sabdar  *   void
8252654012fSReza Sabdar  */
8262654012fSReza Sabdar /*ARGSUSED*/
8272654012fSReza Sabdar void
8282654012fSReza Sabdar ndmpd_data_get_env_v4(ndmp_connection_t *connection, void *body)
8292654012fSReza Sabdar {
8302654012fSReza Sabdar 	ndmp_data_get_env_reply reply;
8312654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
8322654012fSReza Sabdar 
8332654012fSReza Sabdar 	(void) memset((void*)&reply, 0, sizeof (reply));
8342654012fSReza Sabdar 
8352654012fSReza Sabdar 	if (session->ns_data.dd_state != NDMP_DATA_STATE_ACTIVE &&
8362654012fSReza Sabdar 	    session->ns_data.dd_state != NDMP_DATA_STATE_HALTED) {
8372654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Invalid state for the data server.");
8382654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_STATE_ERR;
8392654012fSReza Sabdar 		reply.env.env_len = 0;
8402654012fSReza Sabdar 	} else if (session->ns_data.dd_operation != NDMP_DATA_OP_BACKUP) {
8412654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Backup operation not active.");
8422654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_STATE_ERR;
8432654012fSReza Sabdar 		reply.env.env_len = 0;
8442654012fSReza Sabdar 	} else {
8452654012fSReza Sabdar 		reply.error = NDMP_NO_ERR;
8462654012fSReza Sabdar 		reply.env.env_len = session->ns_data.dd_env_len;
8472654012fSReza Sabdar 		reply.env.env_val = session->ns_data.dd_env;
8482654012fSReza Sabdar 	}
8492654012fSReza Sabdar 
8502654012fSReza Sabdar 	ndmp_send_reply(connection, &reply, "sending data_get_env reply");
8512654012fSReza Sabdar }
8522654012fSReza Sabdar 
8532654012fSReza Sabdar /*
8542654012fSReza Sabdar  * ndmpd_data_get_state_v4
8552654012fSReza Sabdar  *
8562654012fSReza Sabdar  * Request handler. Returns current data state.
8572654012fSReza Sabdar  *
8582654012fSReza Sabdar  * Parameters:
8592654012fSReza Sabdar  *   connection (input) - connection handle.
8602654012fSReza Sabdar  *   body       (input) - request message body.
8612654012fSReza Sabdar  *
8622654012fSReza Sabdar  * Returns:
8632654012fSReza Sabdar  *   void
8642654012fSReza Sabdar  */
8652654012fSReza Sabdar /*ARGSUSED*/
8662654012fSReza Sabdar void
8672654012fSReza Sabdar ndmpd_data_get_state_v4(ndmp_connection_t *connection, void *body)
8682654012fSReza Sabdar {
8692654012fSReza Sabdar 	ndmp_data_get_state_reply_v4 reply;
8702654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
8712654012fSReza Sabdar 
8722654012fSReza Sabdar 	(void) memset((void*)&reply, 0, sizeof (reply));
8732654012fSReza Sabdar 
8742654012fSReza Sabdar 	reply.error = NDMP_NO_ERR;
8752654012fSReza Sabdar 	reply.unsupported = NDMP_DATA_STATE_EST_BYTES_REMAIN_INVALID
8762654012fSReza Sabdar 	    | NDMP_DATA_STATE_EST_TIME_REMAIN_INVALID;
8772654012fSReza Sabdar 	reply.operation = session->ns_data.dd_operation;
8782654012fSReza Sabdar 	reply.state = session->ns_data.dd_state;
8792654012fSReza Sabdar 	reply.halt_reason = session->ns_data.dd_halt_reason;
8802654012fSReza Sabdar 
8812654012fSReza Sabdar 	if (reply.operation == NDMP_DATA_OP_BACKUP)
8822654012fSReza Sabdar 		reply.bytes_processed = long_long_to_quad(
8832654012fSReza Sabdar 		    session->ns_data.dd_module.dm_stats.ms_bytes_processed);
8842654012fSReza Sabdar 	else
8852654012fSReza Sabdar 		reply.bytes_processed =
8862654012fSReza Sabdar 		    long_long_to_quad(ndmpd_data_get_info(session));
8872654012fSReza Sabdar 
8882654012fSReza Sabdar 	reply.est_bytes_remain = long_long_to_quad(0LL);
8892654012fSReza Sabdar 	reply.est_time_remain = 0;
8902654012fSReza Sabdar 	if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE)
8912654012fSReza Sabdar 		ndmp_copy_addr_v4(&reply.data_connection_addr,
8922654012fSReza Sabdar 		    &session->ns_data.dd_data_addr_v4);
8932654012fSReza Sabdar 
8942654012fSReza Sabdar 	reply.read_offset = long_long_to_quad(session->ns_data.dd_read_offset);
8952654012fSReza Sabdar 	reply.read_length = long_long_to_quad(session->ns_data.dd_read_length);
8962654012fSReza Sabdar 
8972654012fSReza Sabdar 	ndmp_send_reply(connection, &reply,
8982654012fSReza Sabdar 	    "sending ndmp_data_get_state_v4 reply");
8992654012fSReza Sabdar 	free(reply.data_connection_addr.tcp_addr_v4);
9002654012fSReza Sabdar }
9012654012fSReza Sabdar 
9022654012fSReza Sabdar 
9032654012fSReza Sabdar /*
9042654012fSReza Sabdar  * ndmpd_data_connect_v4
9052654012fSReza Sabdar  *
9062654012fSReza Sabdar  * Request handler. Connects the data server to either a local
9072654012fSReza Sabdar  * or remote mover.
9082654012fSReza Sabdar  *
9092654012fSReza Sabdar  * Parameters:
9102654012fSReza Sabdar  *   connection (input) - connection handle.
9112654012fSReza Sabdar  *   body       (input) - request message body.
9122654012fSReza Sabdar  *
9132654012fSReza Sabdar  * Returns:
9142654012fSReza Sabdar  *   void
9152654012fSReza Sabdar  */
9162654012fSReza Sabdar void
9172654012fSReza Sabdar ndmpd_data_connect_v4(ndmp_connection_t *connection, void *body)
9182654012fSReza Sabdar {
9192654012fSReza Sabdar 	ndmp_data_connect_request_v4 *request;
9202654012fSReza Sabdar 	ndmp_data_connect_reply_v4 reply;
9212654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
9222654012fSReza Sabdar 
9232654012fSReza Sabdar 	request = (ndmp_data_connect_request_v4 *)body;
9242654012fSReza Sabdar 
9252654012fSReza Sabdar 	(void) memset((void*)&reply, 0, sizeof (reply));
9262654012fSReza Sabdar 
9272654012fSReza Sabdar 	if (!ndmp_valid_v3addr_type(request->addr.addr_type)) {
9282654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
9292654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid address type %d",
9302654012fSReza Sabdar 		    request->addr.addr_type);
9312654012fSReza Sabdar 	} else if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
9322654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_STATE_ERR;
9332654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Invalid state to process connect request.");
9342654012fSReza Sabdar 	} else {
9352654012fSReza Sabdar 		reply.error = NDMP_NO_ERR;
9362654012fSReza Sabdar 	}
9372654012fSReza Sabdar 
9382654012fSReza Sabdar 	if (reply.error != NDMP_NO_ERR) {
9392654012fSReza Sabdar 		ndmp_send_reply(connection, &reply,
9402654012fSReza Sabdar 		    "sending ndmp_data_connect_v4 reply");
9412654012fSReza Sabdar 		return;
9422654012fSReza Sabdar 	}
9432654012fSReza Sabdar 
9442654012fSReza Sabdar 	switch (request->addr.addr_type) {
9452654012fSReza Sabdar 	case NDMP_ADDR_LOCAL:
9462654012fSReza Sabdar 		/*
9472654012fSReza Sabdar 		 * Verify that the mover is listening for a
9482654012fSReza Sabdar 		 * local connection
9492654012fSReza Sabdar 		 */
9502654012fSReza Sabdar 		if (session->ns_mover.md_state != NDMP_MOVER_STATE_LISTEN ||
9512654012fSReza Sabdar 		    session->ns_mover.md_listen_sock != -1) {
9522654012fSReza Sabdar 			reply.error = NDMP_ILLEGAL_STATE_ERR;
9532654012fSReza Sabdar 			NDMP_LOG(LOG_ERR,
9542654012fSReza Sabdar 			    "Mover is not in local listen state.");
9552654012fSReza Sabdar 		} else {
9562654012fSReza Sabdar 			session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE;
9572654012fSReza Sabdar 		}
9582654012fSReza Sabdar 		break;
9592654012fSReza Sabdar 
9602654012fSReza Sabdar 	case NDMP_ADDR_TCP:
9612654012fSReza Sabdar 		reply.error = data_connect_sock_v3(session,
9622654012fSReza Sabdar 		    request->addr.tcp_ip_v4(0), request->addr.tcp_port_v4(0));
9632654012fSReza Sabdar 		break;
9642654012fSReza Sabdar 
9652654012fSReza Sabdar 	default:
9662654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
9672654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid address type %d",
9682654012fSReza Sabdar 		    request->addr.addr_type);
9692654012fSReza Sabdar 	}
9702654012fSReza Sabdar 
9712654012fSReza Sabdar 	if (reply.error == NDMP_NO_ERR)
9722654012fSReza Sabdar 		session->ns_data.dd_state = NDMP_DATA_STATE_CONNECTED;
9732654012fSReza Sabdar 
9742654012fSReza Sabdar 	ndmp_send_reply(connection, &reply,
9752654012fSReza Sabdar 	    "sending ndmp_data_connect_v4 reply");
9762654012fSReza Sabdar }
9772654012fSReza Sabdar 
9782654012fSReza Sabdar /*
9792654012fSReza Sabdar  * ndmpd_data_listen_v4
9802654012fSReza Sabdar  *
9812654012fSReza Sabdar  * Request handler. Configures the server to listen for a connection
9822654012fSReza Sabdar  * from a remote mover.
9832654012fSReza Sabdar  *
9842654012fSReza Sabdar  * Parameters:
9852654012fSReza Sabdar  *   connection (input) - connection handle.
9862654012fSReza Sabdar  *   body       (input) - request message body.
9872654012fSReza Sabdar  *
9882654012fSReza Sabdar  * Returns:
9892654012fSReza Sabdar  *   void
9902654012fSReza Sabdar  */
9912654012fSReza Sabdar void
9922654012fSReza Sabdar ndmpd_data_listen_v4(ndmp_connection_t *connection, void *body)
9932654012fSReza Sabdar {
9942654012fSReza Sabdar 	ndmp_data_listen_request_v4 *request;
9952654012fSReza Sabdar 	ndmp_data_listen_reply_v4 reply;
9962654012fSReza Sabdar 	ndmpd_session_t *session = ndmp_get_client_data(connection);
9972654012fSReza Sabdar 	ulong_t addr;
9982654012fSReza Sabdar 	ushort_t port;
9992654012fSReza Sabdar 
10002654012fSReza Sabdar 	request = (ndmp_data_listen_request_v4 *)body;
10012654012fSReza Sabdar 
10022654012fSReza Sabdar 	(void) memset((void*)&reply, 0, sizeof (reply));
10032654012fSReza Sabdar 
10042654012fSReza Sabdar 	if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
10052654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_STATE_ERR;
10062654012fSReza Sabdar 		NDMP_LOG(LOG_ERR,
10072654012fSReza Sabdar 		    "Invalid internal data state to process listen request.");
10082654012fSReza Sabdar 	} else if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) {
10092654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_STATE_ERR;
10102654012fSReza Sabdar 		NDMP_LOG(LOG_ERR,
10112654012fSReza Sabdar 		    "Invalid mover state to process listen request.");
10122654012fSReza Sabdar 	} else {
10132654012fSReza Sabdar 		reply.error = NDMP_NO_ERR;
10142654012fSReza Sabdar 	}
10152654012fSReza Sabdar 
10162654012fSReza Sabdar 	if (reply.error != NDMP_NO_ERR) {
10172654012fSReza Sabdar 		ndmp_send_reply(connection, &reply,
10182654012fSReza Sabdar 		    "ndmp_data_listen_request_v4 reply");
10192654012fSReza Sabdar 		return;
10202654012fSReza Sabdar 	}
10212654012fSReza Sabdar 
10222654012fSReza Sabdar 	switch (request->addr_type) {
10232654012fSReza Sabdar 	case NDMP_ADDR_LOCAL:
10242654012fSReza Sabdar 		reply.connect_addr.addr_type = request->addr_type;
10252654012fSReza Sabdar 		session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_LOCAL;
10262654012fSReza Sabdar 		break;
10272654012fSReza Sabdar 	case NDMP_ADDR_TCP:
10282654012fSReza Sabdar 		if (create_listen_socket_v3(session, &addr, &port) < 0) {
10292654012fSReza Sabdar 			reply.error = NDMP_IO_ERR;
10302654012fSReza Sabdar 			break;
10312654012fSReza Sabdar 		}
10322654012fSReza Sabdar 
10332654012fSReza Sabdar 		reply.error = NDMP_NO_ERR;
10342654012fSReza Sabdar 		reply.connect_addr.addr_type = request->addr_type;
10352654012fSReza Sabdar 		reply.connect_addr.tcp_addr_v4 =
10362654012fSReza Sabdar 		    ndmp_malloc(sizeof (ndmp_tcp_addr_v4));
10372654012fSReza Sabdar 
10382654012fSReza Sabdar 		reply.connect_addr.tcp_ip_v4(0) = htonl(addr);
10392654012fSReza Sabdar 		reply.connect_addr.tcp_port_v4(0) = htons(port);
10402654012fSReza Sabdar 		reply.connect_addr.tcp_len_v4 = 1;
10412654012fSReza Sabdar 
10422654012fSReza Sabdar 		session->ns_data.dd_data_addr_v4.addr_type = NDMP_ADDR_TCP;
10432654012fSReza Sabdar 		session->ns_data.dd_data_addr_v4.tcp_addr_v4 =
10442654012fSReza Sabdar 		    ndmp_malloc(sizeof (ndmp_tcp_addr_v4));
10452654012fSReza Sabdar 
10462654012fSReza Sabdar 		session->ns_data.dd_data_addr_v4.tcp_ip_v4(0) = addr;
10472654012fSReza Sabdar 		session->ns_data.dd_data_addr_v4.tcp_port_v4(0) = ntohs(port);
10482654012fSReza Sabdar 		session->ns_data.dd_data_addr_v4.tcp_len_v4 = 1;
10492654012fSReza Sabdar 
10502654012fSReza Sabdar 		/* Copy that to data_addr for compatibility */
10512654012fSReza Sabdar 		session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_TCP;
10522654012fSReza Sabdar 		session->ns_data.dd_data_addr.tcp_ip_v3 = addr;
10532654012fSReza Sabdar 		session->ns_data.dd_data_addr.tcp_port_v3 = ntohs(port);
10542654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "listen_socket: %d",
10552654012fSReza Sabdar 		    session->ns_data.dd_listen_sock);
10562654012fSReza Sabdar 		break;
10572654012fSReza Sabdar 
10582654012fSReza Sabdar 	default:
10592654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid address type: %d",
10602654012fSReza Sabdar 		    request->addr_type);
10612654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
10622654012fSReza Sabdar 		break;
10632654012fSReza Sabdar 	}
10642654012fSReza Sabdar 
10652654012fSReza Sabdar 	if (reply.error == NDMP_NO_ERR)
10662654012fSReza Sabdar 		session->ns_data.dd_state = NDMP_DATA_STATE_LISTEN;
10672654012fSReza Sabdar 
10682654012fSReza Sabdar 	ndmp_send_reply(connection, &reply,
10692654012fSReza Sabdar 	    "ndmp_data_listen_request_v4 reply");
10702654012fSReza Sabdar }
10712654012fSReza Sabdar 
10722654012fSReza Sabdar 
10732654012fSReza Sabdar /*
10742654012fSReza Sabdar  * ndmpd_data_start_recover_filehist_v4
10752654012fSReza Sabdar  *
10762654012fSReza Sabdar  * Request handler. Recovers the file history (not supported yet)
10772654012fSReza Sabdar  * This command has an optional support in V4.
10782654012fSReza Sabdar  *
10792654012fSReza Sabdar  * Parameters:
10802654012fSReza Sabdar  *   connection (input) - connection handle.
10812654012fSReza Sabdar  *   body       (input) - request message body.
10822654012fSReza Sabdar  *
10832654012fSReza Sabdar  * Returns:
10842654012fSReza Sabdar  *   void
10852654012fSReza Sabdar  */
10862654012fSReza Sabdar /*ARGSUSED*/
10872654012fSReza Sabdar void
10882654012fSReza Sabdar ndmpd_data_start_recover_filehist_v4(ndmp_connection_t *connection, void *body)
10892654012fSReza Sabdar {
10902654012fSReza Sabdar 	ndmp_data_start_recover_filehist_reply_v4 reply;
10912654012fSReza Sabdar 
10922654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "Request not supported");
10932654012fSReza Sabdar 	reply.error = NDMP_NOT_SUPPORTED_ERR;
10942654012fSReza Sabdar 
10952654012fSReza Sabdar 	ndmp_send_reply(connection, &reply,
10962654012fSReza Sabdar 	    "sending ndmp_data_start_recover_filehist_reply_v4 reply");
10972654012fSReza Sabdar }
10982654012fSReza Sabdar 
10992654012fSReza Sabdar /*
11002654012fSReza Sabdar  * ************************************************************************
11012654012fSReza Sabdar  * LOCALS
11022654012fSReza Sabdar  * ************************************************************************
11032654012fSReza Sabdar  */
11042654012fSReza Sabdar 
11052654012fSReza Sabdar /*
11062654012fSReza Sabdar  * ndmpd_data_error_send
11072654012fSReza Sabdar  *
11082654012fSReza Sabdar  * This function sends the notify message to the client.
11092654012fSReza Sabdar  *
11102654012fSReza Sabdar  * Parameters:
11112654012fSReza Sabdar  *   session (input) - session pointer.
11122654012fSReza Sabdar  *   reason  (input) - halt reason.
11132654012fSReza Sabdar  *
11142654012fSReza Sabdar  * Returns:
11152654012fSReza Sabdar  *   Error code
11162654012fSReza Sabdar  */
11172654012fSReza Sabdar /*ARGSUSED*/
11182654012fSReza Sabdar static int
11192654012fSReza Sabdar ndmpd_data_error_send(ndmpd_session_t *session, ndmp_data_halt_reason reason)
11202654012fSReza Sabdar {
11212654012fSReza Sabdar 	ndmp_notify_data_halted_request req;
11222654012fSReza Sabdar 
11232654012fSReza Sabdar 	req.reason = session->ns_data.dd_halt_reason;
11242654012fSReza Sabdar 	req.text_reason = "";
11252654012fSReza Sabdar 
11262654012fSReza Sabdar 	return (ndmp_send_request(session->ns_connection,
11272654012fSReza Sabdar 	    NDMP_NOTIFY_DATA_HALTED, NDMP_NO_ERR, &req, 0));
11282654012fSReza Sabdar }
11292654012fSReza Sabdar 
11302654012fSReza Sabdar 
11312654012fSReza Sabdar /*
11322654012fSReza Sabdar  * ndmpd_data_error_send_v4
11332654012fSReza Sabdar  *
11342654012fSReza Sabdar  * This function sends the notify message to the client.
11352654012fSReza Sabdar  *
11362654012fSReza Sabdar  * Parameters:
11372654012fSReza Sabdar  *   session (input) - session pointer.
11382654012fSReza Sabdar  *   reason  (input) - halt reason.
11392654012fSReza Sabdar  *
11402654012fSReza Sabdar  * Returns:
11412654012fSReza Sabdar  *   Error code
11422654012fSReza Sabdar  */
11432654012fSReza Sabdar /*ARGSUSED*/
11442654012fSReza Sabdar static int
11452654012fSReza Sabdar ndmpd_data_error_send_v4(ndmpd_session_t *session, ndmp_data_halt_reason reason)
11462654012fSReza Sabdar {
11472654012fSReza Sabdar 	ndmp_notify_data_halted_request_v4 req;
11482654012fSReza Sabdar 
11492654012fSReza Sabdar 	req.reason = session->ns_data.dd_halt_reason;
11502654012fSReza Sabdar 
11512654012fSReza Sabdar 	return ndmp_send_request(session->ns_connection,
11522654012fSReza Sabdar 	    NDMP_NOTIFY_DATA_HALTED, NDMP_NO_ERR, &req, 0);
11532654012fSReza Sabdar }
11542654012fSReza Sabdar 
11552654012fSReza Sabdar 
11562654012fSReza Sabdar /*
11572654012fSReza Sabdar  * ndmpd_data_error
11582654012fSReza Sabdar  *
11592654012fSReza Sabdar  * This function is called when a data error has been detected.
11602654012fSReza Sabdar  * A notify message is sent to the client and the data server is
11612654012fSReza Sabdar  * placed into the halted state.
11622654012fSReza Sabdar  *
11632654012fSReza Sabdar  * Parameters:
11642654012fSReza Sabdar  *   session (input) - session pointer.
11652654012fSReza Sabdar  *   reason  (input) - halt reason.
11662654012fSReza Sabdar  *
11672654012fSReza Sabdar  * Returns:
11682654012fSReza Sabdar  *   void
11692654012fSReza Sabdar  */
11702654012fSReza Sabdar void
11712654012fSReza Sabdar ndmpd_data_error(ndmpd_session_t *session, ndmp_data_halt_reason reason)
11722654012fSReza Sabdar {
11732654012fSReza Sabdar 	if (session->ns_data.dd_state == NDMP_DATA_STATE_IDLE ||
11742654012fSReza Sabdar 	    session->ns_data.dd_state == NDMP_DATA_STATE_HALTED)
11752654012fSReza Sabdar 		return;
11762654012fSReza Sabdar 
11772654012fSReza Sabdar 	if (session->ns_data.dd_operation == NDMP_DATA_OP_BACKUP) {
11782654012fSReza Sabdar 		/*
11792654012fSReza Sabdar 		 * Send/discard any buffered file history data.
11802654012fSReza Sabdar 		 */
11812654012fSReza Sabdar 		ndmpd_file_history_cleanup(session,
11822654012fSReza Sabdar 		    (reason == NDMP_DATA_HALT_SUCCESSFUL ? TRUE : FALSE));
11832654012fSReza Sabdar 
11842654012fSReza Sabdar 		/*
11852654012fSReza Sabdar 		 * If mover local and successful backup, write any
11862654012fSReza Sabdar 		 * remaining buffered data to tape.
11872654012fSReza Sabdar 		 */
11882654012fSReza Sabdar 		if (session->ns_data.dd_data_addr.addr_type
11892654012fSReza Sabdar 		    == NDMP_ADDR_LOCAL && reason == NDMP_DATA_HALT_SUCCESSFUL)
11902654012fSReza Sabdar 			(void) ndmpd_local_write_v3(session, 0, 0);
11912654012fSReza Sabdar 	}
11922654012fSReza Sabdar 
11932654012fSReza Sabdar 	session->ns_data.dd_state = NDMP_DATA_STATE_HALTED;
11942654012fSReza Sabdar 	session->ns_data.dd_halt_reason = reason;
11952654012fSReza Sabdar 
11962654012fSReza Sabdar 	if (session->ns_protocol_version == NDMPV4) {
11972654012fSReza Sabdar 		if (ndmpd_data_error_send_v4(session, reason) < 0)
11982654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG,
11992654012fSReza Sabdar 			    "Error sending notify_data_halted request");
12002654012fSReza Sabdar 	} else {
12012654012fSReza Sabdar 		if (ndmpd_data_error_send(session, reason) < 0)
12022654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG,
12032654012fSReza Sabdar 			    "Error sending notify_data_halted request");
12042654012fSReza Sabdar 	}
12052654012fSReza Sabdar 
12062654012fSReza Sabdar 	if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_TCP) {
12072654012fSReza Sabdar 		if (session->ns_data.dd_sock != -1) {
12082654012fSReza Sabdar 			(void) ndmpd_remove_file_handler(session,
12092654012fSReza Sabdar 			    session->ns_data.dd_sock);
12102654012fSReza Sabdar 			/*
12112654012fSReza Sabdar 			 * ndmpcopy: we use the same socket for the mover,
12122654012fSReza Sabdar 			 * so expect to close when mover is done!
12132654012fSReza Sabdar 			 */
12142654012fSReza Sabdar 			if (session->ns_data.dd_sock !=
12152654012fSReza Sabdar 			    session->ns_mover.md_sock)
12162654012fSReza Sabdar 				(void) close(session->ns_data.dd_sock);
12172654012fSReza Sabdar 
12182654012fSReza Sabdar 			session->ns_data.dd_sock = -1;
12192654012fSReza Sabdar 		}
12202654012fSReza Sabdar 		if (session->ns_data.dd_listen_sock != -1) {
12212654012fSReza Sabdar 			(void) ndmpd_remove_file_handler(session,
12222654012fSReza Sabdar 			    session->ns_data.dd_listen_sock);
12232654012fSReza Sabdar 
12242654012fSReza Sabdar 			(void) close(session->ns_data.dd_listen_sock);
12252654012fSReza Sabdar 			session->ns_data.dd_listen_sock = -1;
12262654012fSReza Sabdar 		}
12272654012fSReza Sabdar 	} else {
12282654012fSReza Sabdar 		ndmpd_mover_error(session, NDMP_MOVER_HALT_CONNECT_CLOSED);
12292654012fSReza Sabdar 	}
12302654012fSReza Sabdar }
12312654012fSReza Sabdar 
12322654012fSReza Sabdar 
12332654012fSReza Sabdar /*
12342654012fSReza Sabdar  * data_accept_connection_v3
12352654012fSReza Sabdar  *
12362654012fSReza Sabdar  * Accept a data connection from a remote mover.
12372654012fSReza Sabdar  * Called by ndmpd_select when a connection is pending on
12382654012fSReza Sabdar  * the data listen socket.
12392654012fSReza Sabdar  *
12402654012fSReza Sabdar  * Parameters:
12412654012fSReza Sabdar  *   cookie  (input) - session pointer.
12422654012fSReza Sabdar  *   fd      (input) - file descriptor.
12432654012fSReza Sabdar  *   mode    (input) - select mode.
12442654012fSReza Sabdar  *
12452654012fSReza Sabdar  * Returns:
12462654012fSReza Sabdar  *   void
12472654012fSReza Sabdar  */
12482654012fSReza Sabdar /*ARGSUSED*/
12492654012fSReza Sabdar static void
12502654012fSReza Sabdar data_accept_connection_v3(void *cookie, int fd, ulong_t mode)
12512654012fSReza Sabdar {
12522654012fSReza Sabdar 	ndmpd_session_t *session = (ndmpd_session_t *)cookie;
12532654012fSReza Sabdar 	int from_len;
12542654012fSReza Sabdar 	struct sockaddr_in from;
12552654012fSReza Sabdar 
12562654012fSReza Sabdar 	from_len = sizeof (from);
12572654012fSReza Sabdar 	session->ns_data.dd_sock = accept(fd, (struct sockaddr *)&from,
12582654012fSReza Sabdar 	    &from_len);
12592654012fSReza Sabdar 
12602654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "sock fd: %d",
12612654012fSReza Sabdar 	    session->ns_data.dd_sock);
12622654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "sin: port %d addr %s",
12632654012fSReza Sabdar 	    ntohs(from.sin_port),
12642654012fSReza Sabdar 	    inet_ntoa(IN_ADDR(from.sin_addr.s_addr)));
12652654012fSReza Sabdar 
12662654012fSReza Sabdar 	(void) ndmpd_remove_file_handler(session, fd);
12672654012fSReza Sabdar 	(void) close(session->ns_data.dd_listen_sock);
12682654012fSReza Sabdar 	session->ns_data.dd_listen_sock = -1;
12692654012fSReza Sabdar 
12702654012fSReza Sabdar 	if (session->ns_data.dd_sock < 0) {
12712654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Accept error: %m");
12722654012fSReza Sabdar 		ndmpd_data_error(session, NDMP_DATA_HALT_CONNECT_ERROR);
12732654012fSReza Sabdar 		return;
12742654012fSReza Sabdar 	}
12752654012fSReza Sabdar 
12762654012fSReza Sabdar 	/*
12772654012fSReza Sabdar 	 * Save the peer address.
12782654012fSReza Sabdar 	 */
12792654012fSReza Sabdar 	session->ns_data.dd_data_addr.tcp_ip_v3 = from.sin_addr.s_addr;
12802654012fSReza Sabdar 	session->ns_data.dd_data_addr.tcp_port_v3 = ntohs(from.sin_port);
12812654012fSReza Sabdar 
1282*97f7c475SJan Kryl 	/* Set the parameter of the new socket */
1283*97f7c475SJan Kryl 	set_socket_options(session->ns_data.dd_sock);
12842654012fSReza Sabdar 
12852654012fSReza Sabdar 	session->ns_data.dd_state = NDMP_DATA_STATE_CONNECTED;
12862654012fSReza Sabdar }
12872654012fSReza Sabdar 
12882654012fSReza Sabdar 
12892654012fSReza Sabdar /*
12902654012fSReza Sabdar  * create_listen_socket_v3
12912654012fSReza Sabdar  *
12922654012fSReza Sabdar  * Creates the data sockets for listening for a remote mover/data
12932654012fSReza Sabdar  * incoming connections.
12942654012fSReza Sabdar  */
12952654012fSReza Sabdar static int
12962654012fSReza Sabdar create_listen_socket_v3(ndmpd_session_t *session, ulong_t *addr, ushort_t *port)
12972654012fSReza Sabdar {
12982654012fSReza Sabdar 	session->ns_data.dd_listen_sock = ndmp_create_socket(addr, port);
12992654012fSReza Sabdar 	if (session->ns_data.dd_listen_sock < 0)
13002654012fSReza Sabdar 		return (-1);
13012654012fSReza Sabdar 
13022654012fSReza Sabdar 	/*
13032654012fSReza Sabdar 	 * Add a file handler for the listen socket.
13042654012fSReza Sabdar 	 * ndmpd_select will call data_accept_connection when a
13052654012fSReza Sabdar 	 * connection is ready to be accepted.
13062654012fSReza Sabdar 	 */
13072654012fSReza Sabdar 	if (ndmpd_add_file_handler(session, (void*)session,
13082654012fSReza Sabdar 	    session->ns_data.dd_listen_sock, NDMPD_SELECT_MODE_READ, HC_MOVER,
13092654012fSReza Sabdar 	    data_accept_connection_v3) < 0) {
13102654012fSReza Sabdar 		(void) close(session->ns_data.dd_listen_sock);
13112654012fSReza Sabdar 		session->ns_data.dd_listen_sock = -1;
13122654012fSReza Sabdar 		return (-1);
13132654012fSReza Sabdar 	}
13142654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "addr: %s:%d",
13152654012fSReza Sabdar 	    inet_ntoa(IN_ADDR(*addr)), ntohs(*port));
13162654012fSReza Sabdar 
13172654012fSReza Sabdar 	return (0);
13182654012fSReza Sabdar }
13192654012fSReza Sabdar 
13202654012fSReza Sabdar 
13212654012fSReza Sabdar /*
13222654012fSReza Sabdar  * data_connect_sock_v3
13232654012fSReza Sabdar  *
13242654012fSReza Sabdar  * Connect the data interface socket to the specified ip/port
13252654012fSReza Sabdar  *
13262654012fSReza Sabdar  * Parameters:
13272654012fSReza Sabdar  *   session (input) - session pointer.
13282654012fSReza Sabdar  *   addr    (input) - IP address
13292654012fSReza Sabdar  *   port    (input) - port number
13302654012fSReza Sabdar  *
13312654012fSReza Sabdar  * Returns:
13322654012fSReza Sabdar  *   NDMP_NO_ERR - backup successfully started.
13332654012fSReza Sabdar  *   otherwise - error code of backup start error.
13342654012fSReza Sabdar  */
13352654012fSReza Sabdar static ndmp_error
13362654012fSReza Sabdar data_connect_sock_v3(ndmpd_session_t *session, ulong_t addr, ushort_t port)
13372654012fSReza Sabdar {
13382654012fSReza Sabdar 	int sock;
13392654012fSReza Sabdar 
13402654012fSReza Sabdar 	sock = ndmp_connect_sock_v3(addr, port);
13412654012fSReza Sabdar 	if (sock < 0)
13422654012fSReza Sabdar 		return (NDMP_CONNECT_ERR);
13432654012fSReza Sabdar 
13442654012fSReza Sabdar 	session->ns_data.dd_sock = sock;
13452654012fSReza Sabdar 	session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_TCP;
13462654012fSReza Sabdar 	session->ns_data.dd_data_addr.tcp_ip_v3 = ntohl(addr);
13472654012fSReza Sabdar 	session->ns_data.dd_data_addr.tcp_port_v3 = port;
13482654012fSReza Sabdar 
13492654012fSReza Sabdar 	return (NDMP_NO_ERR);
13502654012fSReza Sabdar }
13512654012fSReza Sabdar 
13522654012fSReza Sabdar 
13532654012fSReza Sabdar /*
13548c4f9701SJanice Chang  * ndmpd_tar_start_backup_v3
13552654012fSReza Sabdar  *
13562654012fSReza Sabdar  * Start the backup work
13572654012fSReza Sabdar  *
13582654012fSReza Sabdar  * Parameters:
13592654012fSReza Sabdar  *   session   (input) - session pointer.
13602654012fSReza Sabdar  *   bu_type   (input) - backup type.
13612654012fSReza Sabdar  *   env_val   (input) - environment variable array.
13622654012fSReza Sabdar  *   env_len   (input) - length of env_val.
13632654012fSReza Sabdar  *
13642654012fSReza Sabdar  * Returns:
13652654012fSReza Sabdar  *   NDMP_NO_ERR - backup successfully started.
13662654012fSReza Sabdar  *   otherwise - error code of backup start error.
13672654012fSReza Sabdar  */
13682654012fSReza Sabdar static ndmp_error
13698c4f9701SJanice Chang ndmpd_tar_start_backup_v3(ndmpd_session_t *session, char *bu_type,
13708c4f9701SJanice Chang     ndmp_pval *env_val, ulong_t env_len)
13712654012fSReza Sabdar {
13722654012fSReza Sabdar 	int err;
13732654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
13742654012fSReza Sabdar 	ndmpd_module_params_t *params;
13752654012fSReza Sabdar 	ndmp_data_start_backup_reply_v3 reply;
13762654012fSReza Sabdar 
13772654012fSReza Sabdar 	(void) memset((void*)&reply, 0, sizeof (reply));
13782654012fSReza Sabdar 
13792654012fSReza Sabdar 	err = ndmpd_save_env(session, env_val, env_len);
13802654012fSReza Sabdar 	if (err != NDMP_NO_ERR)
13812654012fSReza Sabdar 		return (err);
13822654012fSReza Sabdar 
13832654012fSReza Sabdar 	nlp = ndmp_get_nlp(session);
13842654012fSReza Sabdar 	NDMP_FREE(nlp->nlp_params);
13852654012fSReza Sabdar 	params = nlp->nlp_params = ndmp_malloc(sizeof (ndmpd_module_params_t));
13862654012fSReza Sabdar 	if (!params)
13872654012fSReza Sabdar 		return (NDMP_NO_MEM_ERR);
13882654012fSReza Sabdar 
13892654012fSReza Sabdar 	params->mp_daemon_cookie = (void *)session;
13902654012fSReza Sabdar 	params->mp_module_cookie = &session->ns_data.dd_module.dm_module_cookie;
13912654012fSReza Sabdar 	params->mp_protocol_version = session->ns_protocol_version;
13922654012fSReza Sabdar 	params->mp_operation = NDMP_DATA_OP_BACKUP;
13932654012fSReza Sabdar 	params->mp_get_env_func = ndmpd_api_get_env;
13942654012fSReza Sabdar 	params->mp_add_env_func = ndmpd_api_add_env;
13952654012fSReza Sabdar 	params->mp_set_env_func = ndmpd_api_set_env;
13962654012fSReza Sabdar 	params->mp_get_name_func = 0;
13972654012fSReza Sabdar 	params->mp_dispatch_func = ndmpd_api_dispatch;
13982654012fSReza Sabdar 	params->mp_done_func = ndmpd_api_done_v3;
13992654012fSReza Sabdar 	if (session->ns_protocol_version == NDMPV4)
14002654012fSReza Sabdar 		params->mp_log_func_v3 = ndmpd_api_log_v4;
14012654012fSReza Sabdar 	else
14022654012fSReza Sabdar 		params->mp_log_func_v3 = ndmpd_api_log_v3;
14032654012fSReza Sabdar 
14042654012fSReza Sabdar 	params->mp_add_file_handler_func = ndmpd_api_add_file_handler;
14052654012fSReza Sabdar 	params->mp_remove_file_handler_func = ndmpd_api_remove_file_handler;
14062654012fSReza Sabdar 	params->mp_write_func = ndmpd_api_write_v3;
14072654012fSReza Sabdar 	params->mp_read_func = 0;
14082654012fSReza Sabdar 	params->mp_file_recovered_func = 0;
14092654012fSReza Sabdar 	params->mp_stats = &session->ns_data.dd_module.dm_stats;
14102654012fSReza Sabdar 	session->ns_data.dd_module.dm_module_cookie = 0;
14112654012fSReza Sabdar 
14122654012fSReza Sabdar 	if (strcmp(bu_type, NDMP_DUMP_TYPE) == 0) {
14132654012fSReza Sabdar 		NLP_SET(nlp, NLPF_DUMP);
14142654012fSReza Sabdar 		params->mp_file_history_path_func = 0;
14152654012fSReza Sabdar 		params->mp_file_history_dir_func =
14162654012fSReza Sabdar 		    ndmpd_api_file_history_dir_v3;
14172654012fSReza Sabdar 		params->mp_file_history_node_func =
14182654012fSReza Sabdar 		    ndmpd_api_file_history_node_v3;
14192654012fSReza Sabdar 	} else if (strcmp(bu_type, NDMP_TAR_TYPE) == 0) {
14202654012fSReza Sabdar 		NLP_SET(nlp, NLPF_TAR);
14212654012fSReza Sabdar 		params->mp_file_history_path_func =
14222654012fSReza Sabdar 		    ndmpd_api_file_history_file_v3;
14232654012fSReza Sabdar 		params->mp_file_history_dir_func = 0;
14242654012fSReza Sabdar 		params->mp_file_history_node_func = 0;
14252654012fSReza Sabdar 	} else {
14262654012fSReza Sabdar 		NLP_UNSET(nlp, NLPF_DUMP);
14272654012fSReza Sabdar 		NLP_UNSET(nlp, NLPF_TAR);
14282654012fSReza Sabdar 	}
14292654012fSReza Sabdar 
14302654012fSReza Sabdar 	session->ns_data.dd_module.dm_start_func = ndmpd_tar_backup_starter_v3;
14312654012fSReza Sabdar 	session->ns_data.dd_module.dm_abort_func = ndmpd_tar_backup_abort_v3;
14322654012fSReza Sabdar 
14332654012fSReza Sabdar 	session->ns_data.dd_module.dm_stats.ms_est_bytes_remaining = 0;
14342654012fSReza Sabdar 	session->ns_data.dd_module.dm_stats.ms_est_time_remaining  = 0;
14352654012fSReza Sabdar 	session->ns_data.dd_nlist_v3 = 0;
14362654012fSReza Sabdar 	session->ns_data.dd_nlist_len = 0;
14372654012fSReza Sabdar 	session->ns_data.dd_bytes_left_to_read = 0;
14382654012fSReza Sabdar 	session->ns_data.dd_position = 0;
14392654012fSReza Sabdar 	session->ns_data.dd_discard_length = 0;
14402654012fSReza Sabdar 	session->ns_data.dd_read_offset = 0;
14412654012fSReza Sabdar 	session->ns_data.dd_read_length = 0;
14422654012fSReza Sabdar 
14432654012fSReza Sabdar 	reply.error = ndmp_backup_get_params_v3(session, params);
14442654012fSReza Sabdar 	if (reply.error != NDMP_NO_ERR) {
14452654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "err: %d", err);
14462654012fSReza Sabdar 		NDMP_FREE(nlp->nlp_params);
14472654012fSReza Sabdar 		return (reply.error);
14482654012fSReza Sabdar 	}
14492654012fSReza Sabdar 
14502654012fSReza Sabdar 	reply.error = NDMP_NO_ERR;
14512654012fSReza Sabdar 	if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
14522654012fSReza Sabdar 	    &reply) < 0) {
14532654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Sending data_start_backup_v3 reply");
14542654012fSReza Sabdar 		return (NDMP_NO_ERR);
14552654012fSReza Sabdar 	}
14562654012fSReza Sabdar 
14572654012fSReza Sabdar 	NS_INC(nbk);
14582654012fSReza Sabdar 	session->ns_data.dd_state = NDMP_DATA_STATE_ACTIVE;
14592654012fSReza Sabdar 	session->ns_data.dd_operation = NDMP_DATA_OP_BACKUP;
14602654012fSReza Sabdar 	session->ns_data.dd_abort = FALSE;
14612654012fSReza Sabdar 
14622654012fSReza Sabdar 	/*
14632654012fSReza Sabdar 	 * perform the backup
14642654012fSReza Sabdar 	 *
14658c4f9701SJanice Chang 	 * Cannot wait for the thread to exit as we are replying to the
14662654012fSReza Sabdar 	 * client request here.
14672654012fSReza Sabdar 	 */
14682654012fSReza Sabdar 	err = pthread_create(NULL, NULL,
14692654012fSReza Sabdar 	    (funct_t)session->ns_data.dd_module.dm_start_func,
14702654012fSReza Sabdar 	    params);
14712654012fSReza Sabdar 	if (err != 0) {
14722654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Can't start backup session.");
14732654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
14742654012fSReza Sabdar 	}
14752654012fSReza Sabdar 
14762654012fSReza Sabdar 	return (NDMP_NO_ERR);
14772654012fSReza Sabdar }
14782654012fSReza Sabdar 
14792654012fSReza Sabdar /*
14808c4f9701SJanice Chang  * ndmpd_tar_start_recover_v3
14812654012fSReza Sabdar  *
14822654012fSReza Sabdar  * Start the restore work
14832654012fSReza Sabdar  *
14842654012fSReza Sabdar  * Parameters:
14852654012fSReza Sabdar  *   session   (input) - session pointer.
14862654012fSReza Sabdar  *   bu_type   (input) - backup type.
14872654012fSReza Sabdar  *   env_val   (input) - environment variable array.
14882654012fSReza Sabdar  *   env_len   (input) - length of env_val.
14898c4f9701SJanice Chang  *   nlist_val (input) - list of files.
14908c4f9701SJanice Chang  *   nlist_len (input) - length of nlist_val.
14912654012fSReza Sabdar  *
14922654012fSReza Sabdar  * Returns:
14932654012fSReza Sabdar  *   NDMP_NO_ERR - recover successfully started.
14942654012fSReza Sabdar  *   otherwise   - error code of recover start error.
14952654012fSReza Sabdar  */
14962654012fSReza Sabdar static ndmp_error
14978c4f9701SJanice Chang ndmpd_tar_start_recover_v3(ndmpd_session_t *session,
14988c4f9701SJanice Chang     ndmp_pval *env_val, ulong_t env_len, ndmp_name_v3 *nlist_val,
14998c4f9701SJanice Chang     ulong_t nlist_len)
15002654012fSReza Sabdar {
15012654012fSReza Sabdar 	ndmp_data_start_recover_reply_v3 reply;
15022654012fSReza Sabdar 	ndmpd_module_params_t *params;
15032654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
15042654012fSReza Sabdar 	int err;
15052654012fSReza Sabdar 
15062654012fSReza Sabdar 	(void) memset((void*)&reply, 0, sizeof (reply));
15072654012fSReza Sabdar 
15082654012fSReza Sabdar 	nlp = ndmp_get_nlp(session);
15092654012fSReza Sabdar 	NDMP_FREE(nlp->nlp_params);
15102654012fSReza Sabdar 	params = nlp->nlp_params = ndmp_malloc(sizeof (ndmpd_module_params_t));
15112654012fSReza Sabdar 	if (!params) {
15122654012fSReza Sabdar 		return (NDMP_NO_MEM_ERR);
15132654012fSReza Sabdar 	}
15142654012fSReza Sabdar 
15152654012fSReza Sabdar 	reply.error = ndmpd_save_env(session, env_val, env_len);
15162654012fSReza Sabdar 	if (reply.error != NDMP_NO_ERR) {
15172654012fSReza Sabdar 		NDMP_FREE(nlp->nlp_params);
15182654012fSReza Sabdar 		return (NDMP_NO_MEM_ERR);
15192654012fSReza Sabdar 	}
15202654012fSReza Sabdar 
15212654012fSReza Sabdar 	reply.error = ndmpd_save_nlist_v3(session, nlist_val, nlist_len);
15222654012fSReza Sabdar 	if (reply.error != NDMP_NO_ERR) {
15232654012fSReza Sabdar 		NDMP_FREE(nlp->nlp_params);
15242654012fSReza Sabdar 		return (NDMP_NO_MEM_ERR);
15252654012fSReza Sabdar 	}
15262654012fSReza Sabdar 
15272654012fSReza Sabdar 	/*
15282654012fSReza Sabdar 	 * Setup restore parameters.
15292654012fSReza Sabdar 	 */
15302654012fSReza Sabdar 	params->mp_daemon_cookie = (void *)session;
15312654012fSReza Sabdar 	params->mp_module_cookie = &session->ns_data.dd_module.dm_module_cookie;
15322654012fSReza Sabdar 	params->mp_protocol_version = session->ns_protocol_version;
15332654012fSReza Sabdar 	params->mp_operation = NDMP_DATA_OP_RECOVER;
15342654012fSReza Sabdar 	params->mp_get_env_func = ndmpd_api_get_env;
15352654012fSReza Sabdar 	params->mp_add_env_func = ndmpd_api_add_env;
15362654012fSReza Sabdar 	params->mp_set_env_func = ndmpd_api_set_env;
15372654012fSReza Sabdar 	params->mp_get_name_func = ndmpd_api_get_name_v3;
15382654012fSReza Sabdar 	params->mp_dispatch_func = ndmpd_api_dispatch;
15392654012fSReza Sabdar 	params->mp_done_func = ndmpd_api_done_v3;
15402654012fSReza Sabdar 	if (session->ns_protocol_version == NDMPV4) {
15412654012fSReza Sabdar 		params->mp_log_func_v3 = ndmpd_api_log_v4;
15422654012fSReza Sabdar 		params->mp_file_recovered_func = ndmpd_api_file_recovered_v4;
15432654012fSReza Sabdar 	} else {
15442654012fSReza Sabdar 		params->mp_log_func_v3 = ndmpd_api_log_v3;
15452654012fSReza Sabdar 		params->mp_file_recovered_func = ndmpd_api_file_recovered_v3;
15462654012fSReza Sabdar 	}
15472654012fSReza Sabdar 
15482654012fSReza Sabdar 	params->mp_add_file_handler_func = ndmpd_api_add_file_handler;
15492654012fSReza Sabdar 	params->mp_remove_file_handler_func = ndmpd_api_remove_file_handler;
15502654012fSReza Sabdar 	params->mp_write_func = 0;
15512654012fSReza Sabdar 	params->mp_file_history_path_func = 0;
15522654012fSReza Sabdar 	params->mp_file_history_dir_func = 0;
15532654012fSReza Sabdar 	params->mp_file_history_node_func = 0;
15542654012fSReza Sabdar 	params->mp_read_func = ndmpd_api_read_v3;
15552654012fSReza Sabdar 	params->mp_seek_func = ndmpd_api_seek_v3;
15562654012fSReza Sabdar 	params->mp_stats = &session->ns_data.dd_module.dm_stats;
15572654012fSReza Sabdar 
15582654012fSReza Sabdar 	session->ns_data.dd_module.dm_module_cookie = 0;
15592654012fSReza Sabdar 	session->ns_data.dd_module.dm_start_func = ndmpd_tar_restore_starter_v3;
15602654012fSReza Sabdar 	session->ns_data.dd_module.dm_abort_func = ndmpd_tar_restore_abort_v3;
15612654012fSReza Sabdar 	session->ns_data.dd_module.dm_stats.ms_est_bytes_remaining = 0;
15622654012fSReza Sabdar 	session->ns_data.dd_module.dm_stats.ms_est_time_remaining = 0;
15632654012fSReza Sabdar 	session->ns_data.dd_bytes_left_to_read = 0;
15642654012fSReza Sabdar 	session->ns_data.dd_position = 0;
15652654012fSReza Sabdar 	session->ns_data.dd_discard_length = 0;
15662654012fSReza Sabdar 	session->ns_data.dd_read_offset = 0;
15672654012fSReza Sabdar 	session->ns_data.dd_read_length = 0;
15682654012fSReza Sabdar 
15692654012fSReza Sabdar 	err = ndmp_restore_get_params_v3(session, params);
15702654012fSReza Sabdar 	if (err != NDMP_NO_ERR) {
15712654012fSReza Sabdar 		NDMP_FREE(nlp->nlp_params);
15722654012fSReza Sabdar 		return (err);
15732654012fSReza Sabdar 	}
15742654012fSReza Sabdar 
15752654012fSReza Sabdar 	reply.error = NDMP_NO_ERR;
15762654012fSReza Sabdar 	if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
15772654012fSReza Sabdar 	    &reply) < 0) {
15782654012fSReza Sabdar 		NDMP_FREE(nlp->nlp_params);
15792654012fSReza Sabdar 		ndmpd_free_nlist_v3(session);
15802654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
15812654012fSReza Sabdar 		    "Error sending ndmp_data_start_recover_reply");
15822654012fSReza Sabdar 		ndmpd_data_error(session, NDMP_DATA_HALT_CONNECT_ERROR);
15832654012fSReza Sabdar 		return (NDMP_NO_ERR);
15842654012fSReza Sabdar 	}
15852654012fSReza Sabdar 
15862654012fSReza Sabdar 	NS_INC(nrs);
15872654012fSReza Sabdar 	session->ns_data.dd_state = NDMP_DATA_STATE_ACTIVE;
15882654012fSReza Sabdar 	session->ns_data.dd_operation = NDMP_DATA_OP_RECOVER;
15892654012fSReza Sabdar 	session->ns_data.dd_abort = FALSE;
15902654012fSReza Sabdar 
15912654012fSReza Sabdar 	/*
15922654012fSReza Sabdar 	 * perform the restore
15932654012fSReza Sabdar 	 *
15942654012fSReza Sabdar 	 * Cannot wait for the thread to exit as we are replying to the
15952654012fSReza Sabdar 	 * client request here.
15962654012fSReza Sabdar 	 */
15972654012fSReza Sabdar 	err = pthread_create(NULL, NULL,
15982654012fSReza Sabdar 	    (funct_t)session->ns_data.dd_module.dm_start_func,
15992654012fSReza Sabdar 	    params);
16002654012fSReza Sabdar 
16012654012fSReza Sabdar 	if (err != 0) {
16022654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Can't start recover session.");
16032654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
16042654012fSReza Sabdar 	}
16052654012fSReza Sabdar 	return (NDMP_NO_ERR);
16062654012fSReza Sabdar }
16072654012fSReza Sabdar 
16088c4f9701SJanice Chang static ndmp_error
16098c4f9701SJanice Chang ndmpd_zfs_start_op(ndmpd_session_t *session, ndmp_pval *env_val,
16108c4f9701SJanice Chang     ulong_t env_len, ndmp_name_v3 *nlist_val, ulong_t nlist_len,
16118c4f9701SJanice Chang     enum ndmp_data_operation op)
16128c4f9701SJanice Chang {
16138c4f9701SJanice Chang 	ndmpd_zfs_args_t *ndmpd_zfs_args = &session->ns_ndmpd_zfs_args;
16148c4f9701SJanice Chang 	ndmp_data_start_backup_reply_v3 backup_reply;
16158c4f9701SJanice Chang 	ndmp_data_start_recover_reply_v3 recover_reply;
16168c4f9701SJanice Chang 	pthread_t tid;
16178c4f9701SJanice Chang 	void *reply;
16188c4f9701SJanice Chang 	char str[8];
16198c4f9701SJanice Chang 	int err;
16208c4f9701SJanice Chang 
16218c4f9701SJanice Chang 	if (ndmpd_zfs_init(session) != 0)
16228c4f9701SJanice Chang 		return (NDMP_UNDEFINED_ERR);
16238c4f9701SJanice Chang 
16248c4f9701SJanice Chang 	err = ndmpd_save_env(session, env_val, env_len);
16258c4f9701SJanice Chang 	if (err != NDMP_NO_ERR) {
16268c4f9701SJanice Chang 		ndmpd_zfs_fini(ndmpd_zfs_args);
16278c4f9701SJanice Chang 		return (err);
16288c4f9701SJanice Chang 	}
16298c4f9701SJanice Chang 
16308c4f9701SJanice Chang 	switch (op) {
16318c4f9701SJanice Chang 	case NDMP_DATA_OP_BACKUP:
16328c4f9701SJanice Chang 		if (!ndmpd_zfs_backup_parms_valid(ndmpd_zfs_args)) {
16338c4f9701SJanice Chang 			ndmpd_zfs_fini(ndmpd_zfs_args);
16348c4f9701SJanice Chang 			return (NDMP_ILLEGAL_ARGS_ERR);
16358c4f9701SJanice Chang 		}
16368c4f9701SJanice Chang 
16378c4f9701SJanice Chang 		if (ndmpd_zfs_pre_backup(ndmpd_zfs_args)) {
16388c4f9701SJanice Chang 			NDMP_LOG(LOG_ERR, "pre_backup error");
16398c4f9701SJanice Chang 			return (NDMP_ILLEGAL_ARGS_ERR);
16408c4f9701SJanice Chang 		}
16418c4f9701SJanice Chang 
16428c4f9701SJanice Chang 		session->ns_data.dd_module.dm_start_func =
16438c4f9701SJanice Chang 		    ndmpd_zfs_backup_starter;
16448c4f9701SJanice Chang 		(void) strlcpy(str, "backup", 8);
16458c4f9701SJanice Chang 		break;
16468c4f9701SJanice Chang 	case NDMP_DATA_OP_RECOVER:
16478c4f9701SJanice Chang 		err = ndmpd_save_nlist_v3(session, nlist_val, nlist_len);
16488c4f9701SJanice Chang 		if (err != NDMP_NO_ERR) {
16498c4f9701SJanice Chang 			ndmpd_zfs_fini(ndmpd_zfs_args);
16508c4f9701SJanice Chang 			return (NDMP_NO_MEM_ERR);
16518c4f9701SJanice Chang 		}
16528c4f9701SJanice Chang 
16538c4f9701SJanice Chang 		if (!ndmpd_zfs_restore_parms_valid(ndmpd_zfs_args)) {
16548c4f9701SJanice Chang 			ndmpd_zfs_fini(ndmpd_zfs_args);
16558c4f9701SJanice Chang 			return (NDMP_ILLEGAL_ARGS_ERR);
16568c4f9701SJanice Chang 		}
16578c4f9701SJanice Chang 
16588c4f9701SJanice Chang 		if (ndmpd_zfs_pre_restore(ndmpd_zfs_args)) {
16598c4f9701SJanice Chang 			NDMP_LOG(LOG_ERR, "pre_restore error");
16608c4f9701SJanice Chang 			(void) ndmpd_zfs_post_restore(ndmpd_zfs_args);
16618c4f9701SJanice Chang 			return (NDMP_ILLEGAL_ARGS_ERR);
16628c4f9701SJanice Chang 		}
16638c4f9701SJanice Chang 		session->ns_data.dd_module.dm_start_func =
16648c4f9701SJanice Chang 		    ndmpd_zfs_restore_starter;
16658c4f9701SJanice Chang 		(void) strlcpy(str, "recover", 8);
16668c4f9701SJanice Chang 		break;
16678c4f9701SJanice Chang 	}
16688c4f9701SJanice Chang 
16698c4f9701SJanice Chang 	ndmpd_zfs_params->mp_operation = op;
16708c4f9701SJanice Chang 	session->ns_data.dd_operation = op;
16718c4f9701SJanice Chang 	session->ns_data.dd_module.dm_abort_func = ndmpd_zfs_abort;
16728c4f9701SJanice Chang 	session->ns_data.dd_state = NDMP_DATA_STATE_ACTIVE;
16738c4f9701SJanice Chang 	session->ns_data.dd_abort = FALSE;
16748c4f9701SJanice Chang 
16758c4f9701SJanice Chang 	if (op == NDMP_DATA_OP_BACKUP) {
16768c4f9701SJanice Chang 		(void) memset((void*)&backup_reply, 0, sizeof (backup_reply));
16778c4f9701SJanice Chang 		backup_reply.error = NDMP_NO_ERR;
16788c4f9701SJanice Chang 		reply = &backup_reply;
16798c4f9701SJanice Chang 	} else {
16808c4f9701SJanice Chang 		(void) memset((void*)&recover_reply, 0, sizeof (recover_reply));
16818c4f9701SJanice Chang 		recover_reply.error = NDMP_NO_ERR;
16828c4f9701SJanice Chang 		reply = &recover_reply;
16838c4f9701SJanice Chang 	}
16848c4f9701SJanice Chang 
16858c4f9701SJanice Chang 	if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
16868c4f9701SJanice Chang 	    reply) < 0) {
16878c4f9701SJanice Chang 		NDMP_LOG(LOG_DEBUG, "Sending data_start_%s_v3 reply", str);
16888c4f9701SJanice Chang 		if (op == NDMP_DATA_OP_RECOVER)
16898c4f9701SJanice Chang 			ndmpd_data_error(session, NDMP_DATA_HALT_CONNECT_ERROR);
16908c4f9701SJanice Chang 		ndmpd_zfs_fini(ndmpd_zfs_args);
16918c4f9701SJanice Chang 		return (NDMP_NO_ERR);
16928c4f9701SJanice Chang 	}
16938c4f9701SJanice Chang 
16948c4f9701SJanice Chang 	err = pthread_create(&tid, NULL,
16958c4f9701SJanice Chang 	    (funct_t)session->ns_data.dd_module.dm_start_func, ndmpd_zfs_args);
16968c4f9701SJanice Chang 
16978c4f9701SJanice Chang 	if (err) {
16988c4f9701SJanice Chang 		NDMP_LOG(LOG_ERR, "Can't start %s session (errno %d)",
16998c4f9701SJanice Chang 		    str, err);
17008c4f9701SJanice Chang 		ndmpd_zfs_fini(ndmpd_zfs_args);
17018c4f9701SJanice Chang 		MOD_DONE(ndmpd_zfs_params, -1);
17028c4f9701SJanice Chang 		return (NDMP_NO_ERR);
17038c4f9701SJanice Chang 	}
17048c4f9701SJanice Chang 
17058c4f9701SJanice Chang 	(void) pthread_detach(tid);
17068c4f9701SJanice Chang 
17078c4f9701SJanice Chang 	if (op == NDMP_DATA_OP_BACKUP)
17088c4f9701SJanice Chang 		NS_INC(nbk);
17098c4f9701SJanice Chang 	else
17108c4f9701SJanice Chang 		NS_INC(nrs);
17118c4f9701SJanice Chang 
17128c4f9701SJanice Chang 	ndmpd_zfs_dma_log(ndmpd_zfs_args, NDMP_LOG_NORMAL,
17138c4f9701SJanice Chang 	    "'zfs' %s starting\n", str);
17148c4f9701SJanice Chang 
17158c4f9701SJanice Chang 	return (NDMP_NO_ERR);
17168c4f9701SJanice Chang }
17172654012fSReza Sabdar 
17182654012fSReza Sabdar /*
17192654012fSReza Sabdar  * discard_data_v3
17202654012fSReza Sabdar  *
17212654012fSReza Sabdar  * Read and discard data from the data connection.
17222654012fSReza Sabdar  * Called when a module has called ndmpd_seek() prior to
17232654012fSReza Sabdar  * reading all of the data from the previous seek.
17242654012fSReza Sabdar  *
17252654012fSReza Sabdar  * Parameters:
17262654012fSReza Sabdar  *   session (input) - session pointer.
17272654012fSReza Sabdar  *
17282654012fSReza Sabdar  * Returns:
17292654012fSReza Sabdar  *   number of bytes read and discarded.
17302654012fSReza Sabdar  *  -1 - error.
17312654012fSReza Sabdar  */
17322654012fSReza Sabdar static int
17332654012fSReza Sabdar discard_data_v3(ndmpd_session_t *session, ulong_t length)
17342654012fSReza Sabdar {
17352654012fSReza Sabdar 	static char buf[MAX_RECORD_SIZE];
17362654012fSReza Sabdar 	int n, toread;
17372654012fSReza Sabdar 
17382654012fSReza Sabdar 	toread = (length < MAX_RECORD_SIZE) ? length :
17392654012fSReza Sabdar 	    MAX_RECORD_SIZE;
17402654012fSReza Sabdar 
17412654012fSReza Sabdar 	/* Read and discard the data. */
17422654012fSReza Sabdar 	n = read(session->ns_data.dd_sock, buf, toread);
17432654012fSReza Sabdar 	if (n < 0) {
17442654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Socket read error: %m.");
17452654012fSReza Sabdar 		n = -1;
17462654012fSReza Sabdar 	}
17472654012fSReza Sabdar 
17482654012fSReza Sabdar 	return (n);
17492654012fSReza Sabdar }
17502654012fSReza Sabdar 
17512654012fSReza Sabdar 
17522654012fSReza Sabdar /*
17532654012fSReza Sabdar  * ndmpd_remote_read_v3
17542654012fSReza Sabdar  *
17552654012fSReza Sabdar  * Reads data from the remote mover.
17562654012fSReza Sabdar  *
17572654012fSReza Sabdar  * Parameters:
17582654012fSReza Sabdar  *   session (input) - session pointer.
17592654012fSReza Sabdar  *   data    (input) - data to be written.
17602654012fSReza Sabdar  *   length  (input) - data length.
17612654012fSReza Sabdar  *
17622654012fSReza Sabdar  * Returns:
17632654012fSReza Sabdar  *   0 - data successfully read.
17642654012fSReza Sabdar  *  -1 - error.
17652654012fSReza Sabdar  */
17662654012fSReza Sabdar int
17672654012fSReza Sabdar ndmpd_remote_read_v3(ndmpd_session_t *session, char *data, ulong_t length)
17682654012fSReza Sabdar {
17692654012fSReza Sabdar 	ulong_t count;
17702654012fSReza Sabdar 	ulong_t len;
17712654012fSReza Sabdar 	ssize_t n;
17722654012fSReza Sabdar 	ndmp_notify_data_read_request request;
17732654012fSReza Sabdar 	tlm_job_stats_t *jstat;
17742654012fSReza Sabdar 	longlong_t fsize;
17752654012fSReza Sabdar 
17762654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "ns_data.dd_xx: [%llu, %llu, %llu, %llu, %llu]",
17772654012fSReza Sabdar 	    session->ns_data.dd_bytes_left_to_read,
17782654012fSReza Sabdar 	    session->ns_data.dd_read_offset,
17792654012fSReza Sabdar 	    session->ns_data.dd_read_length,
17802654012fSReza Sabdar 	    session->ns_data.dd_position,
17812654012fSReza Sabdar 	    session->ns_data.dd_discard_length);
17822654012fSReza Sabdar 
17832654012fSReza Sabdar 	count = 0;
17842654012fSReza Sabdar 	while (count < length) {
17852654012fSReza Sabdar 		len = length - count;
17862654012fSReza Sabdar 
17872654012fSReza Sabdar 		/*
17882654012fSReza Sabdar 		 * If the end of the seek window has been reached then
17892654012fSReza Sabdar 		 * send an ndmp_read request to the client.
17902654012fSReza Sabdar 		 * The NDMP client will then send a mover_data_read request to
17912654012fSReza Sabdar 		 * the remote mover and the mover will send more data.
17922654012fSReza Sabdar 		 * This condition can occur if the module attempts to read past
17932654012fSReza Sabdar 		 * a seek window set via a prior call to ndmpd_seek() or
17942654012fSReza Sabdar 		 * the module has not issued a seek. If no seek was issued then
17952654012fSReza Sabdar 		 * pretend that a seek was issued to read the entire tape.
17962654012fSReza Sabdar 		 */
17972654012fSReza Sabdar 		if (session->ns_data.dd_bytes_left_to_read == 0) {
17982654012fSReza Sabdar 			/* ndmpd_seek() never called? */
17992654012fSReza Sabdar 			if (session->ns_data.dd_read_length == 0) {
18002654012fSReza Sabdar 				session->ns_data.dd_bytes_left_to_read = ~0LL;
18012654012fSReza Sabdar 				session->ns_data.dd_read_offset = 0LL;
18022654012fSReza Sabdar 				session->ns_data.dd_read_length = ~0LL;
18032654012fSReza Sabdar 			} else {
18042654012fSReza Sabdar 				/*
18052654012fSReza Sabdar 				 * While restoring a file, restoreFile()
18062654012fSReza Sabdar 				 * records the number of bytes still need to
18072654012fSReza Sabdar 				 * be restored.  We use this as a guidance
18082654012fSReza Sabdar 				 * when asking for data from the tape.
18092654012fSReza Sabdar 				 */
18102654012fSReza Sabdar 				jstat = session->ns_ndmp_lbr_params->nlp_jstat;
18112654012fSReza Sabdar 				fsize = jstat->js_bytes_in_file;
18122654012fSReza Sabdar 
18132654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG, "bytes_left [%llu / %u]",
18142654012fSReza Sabdar 				    fsize, len);
18152654012fSReza Sabdar 
18162654012fSReza Sabdar 				/*
18172654012fSReza Sabdar 				 * Fall back to the old way if fsize if too
18182654012fSReza Sabdar 				 * small.
18192654012fSReza Sabdar 				 */
18202654012fSReza Sabdar 				if (fsize < len)
18212654012fSReza Sabdar 					fsize = len;
18222654012fSReza Sabdar 
18232654012fSReza Sabdar 				session->ns_data.dd_bytes_left_to_read = fsize;
18242654012fSReza Sabdar 				session->ns_data.dd_read_offset =
18252654012fSReza Sabdar 				    session->ns_data.dd_position;
18262654012fSReza Sabdar 				session->ns_data.dd_read_length = fsize;
18272654012fSReza Sabdar 			}
18282654012fSReza Sabdar 
18292654012fSReza Sabdar 			request.offset =
18302654012fSReza Sabdar 			    long_long_to_quad(session->ns_data.dd_read_offset);
18312654012fSReza Sabdar 			request.length =
18322654012fSReza Sabdar 			    long_long_to_quad(session->ns_data.dd_read_length);
18332654012fSReza Sabdar 
18342654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "to NOTIFY_DATA_READ [%llu, %llu]",
18352654012fSReza Sabdar 			    session->ns_data.dd_read_offset,
18362654012fSReza Sabdar 			    session->ns_data.dd_read_length);
18372654012fSReza Sabdar 
18387bc22e45SReza Sabdar 			if (ndmp_send_request_lock(session->ns_connection,
18392654012fSReza Sabdar 			    NDMP_NOTIFY_DATA_READ, NDMP_NO_ERR,
18402654012fSReza Sabdar 			    &request, 0) < 0) {
18412654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
18422654012fSReza Sabdar 				    "Sending notify_data_read request");
18432654012fSReza Sabdar 				return (-1);
18442654012fSReza Sabdar 			}
18452654012fSReza Sabdar 		}
18462654012fSReza Sabdar 
18472654012fSReza Sabdar 		/*
18482654012fSReza Sabdar 		 * If the module called ndmpd_seek() prior to reading all of the
18492654012fSReza Sabdar 		 * data that the remote mover was requested to send, then the
18502654012fSReza Sabdar 		 * excess data from the seek has to be discarded.
18512654012fSReza Sabdar 		 */
18522654012fSReza Sabdar 		if (session->ns_data.dd_discard_length != 0) {
18532654012fSReza Sabdar 			n = discard_data_v3(session,
18542654012fSReza Sabdar 			    (ulong_t)session->ns_data.dd_discard_length);
18552654012fSReza Sabdar 			if (n < 0)
18562654012fSReza Sabdar 				return (-1);
18572654012fSReza Sabdar 
18582654012fSReza Sabdar 			session->ns_data.dd_discard_length -= n;
18592654012fSReza Sabdar 			continue;
18602654012fSReza Sabdar 		}
18612654012fSReza Sabdar 
18622654012fSReza Sabdar 		/*
18632654012fSReza Sabdar 		 * Don't attempt to read more data than the remote is sending.
18642654012fSReza Sabdar 		 */
18652654012fSReza Sabdar 		if (len > session->ns_data.dd_bytes_left_to_read)
18662654012fSReza Sabdar 			len = session->ns_data.dd_bytes_left_to_read;
18672654012fSReza Sabdar 
18682654012fSReza Sabdar 		if ((n = read(session->ns_data.dd_sock, &data[count],
18692654012fSReza Sabdar 		    len)) < 0) {
18702654012fSReza Sabdar 			NDMP_LOG(LOG_ERR, "Socket read error: %m.");
18712654012fSReza Sabdar 			return (-1);
18722654012fSReza Sabdar 		}
18732654012fSReza Sabdar 
18742654012fSReza Sabdar 		/* read returns 0 if the connection was closed */
18752654012fSReza Sabdar 		if (n == 0) {
18762654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "n 0 errno %d",
18772654012fSReza Sabdar 			    errno);
18782654012fSReza Sabdar 			return (-1);
18792654012fSReza Sabdar 		}
18802654012fSReza Sabdar 
18812654012fSReza Sabdar 		count += n;
18822654012fSReza Sabdar 		session->ns_data.dd_bytes_left_to_read -= n;
18832654012fSReza Sabdar 		session->ns_data.dd_position += n;
18842654012fSReza Sabdar 	}
18852654012fSReza Sabdar 	return (0);
18862654012fSReza Sabdar }
18872654012fSReza Sabdar 
18882654012fSReza Sabdar /*
18892654012fSReza Sabdar  * nlp_release_job_stat
18902654012fSReza Sabdar  *
18912654012fSReza Sabdar  * Unreference the job statistics
18922654012fSReza Sabdar  *
18932654012fSReza Sabdar  * Parameters:
18942654012fSReza Sabdar  *   session (input) - session pointer.
18952654012fSReza Sabdar  *
18962654012fSReza Sabdar  * Returns:
18972654012fSReza Sabdar  *   void
18982654012fSReza Sabdar  */
18992654012fSReza Sabdar static void
19002654012fSReza Sabdar nlp_release_job_stat(ndmpd_session_t *session)
19012654012fSReza Sabdar {
19022654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
19032654012fSReza Sabdar 
19042654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
19052654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
19062654012fSReza Sabdar 		return;
19072654012fSReza Sabdar 	}
19082654012fSReza Sabdar 	if (nlp->nlp_jstat != NULL) {
19092654012fSReza Sabdar 		nlp->nlp_bytes_total =
19102654012fSReza Sabdar 		    (u_longlong_t)nlp->nlp_jstat->js_bytes_total;
19112654012fSReza Sabdar 		tlm_un_ref_job_stats(nlp->nlp_jstat->js_job_name);
19122654012fSReza Sabdar 		nlp->nlp_jstat = NULL;
19132654012fSReza Sabdar 	} else
19142654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "JSTAT == NULL");
19152654012fSReza Sabdar }
19162654012fSReza Sabdar 
19172654012fSReza Sabdar 
19182654012fSReza Sabdar /* *** ndmpd global internal functions *********************************** */
19192654012fSReza Sabdar 
19202654012fSReza Sabdar /*
19212654012fSReza Sabdar  * ndmpd_data_init
19222654012fSReza Sabdar  *
19232654012fSReza Sabdar  * Initializes data specific session variables.
19242654012fSReza Sabdar  *
19252654012fSReza Sabdar  * Parameters:
19262654012fSReza Sabdar  *   session (input) - session pointer.
19272654012fSReza Sabdar  *
19282654012fSReza Sabdar  * Returns:
19292654012fSReza Sabdar  *   void
19302654012fSReza Sabdar  */
19312654012fSReza Sabdar int
19322654012fSReza Sabdar ndmpd_data_init(ndmpd_session_t *session)
19332654012fSReza Sabdar {
19342654012fSReza Sabdar 	session->ns_data.dd_operation = NDMP_DATA_OP_NOACTION;
19352654012fSReza Sabdar 	session->ns_data.dd_state = NDMP_DATA_STATE_IDLE;
19362654012fSReza Sabdar 	session->ns_data.dd_halt_reason = NDMP_DATA_HALT_NA;
19372654012fSReza Sabdar 	session->ns_data.dd_abort = FALSE;
19382654012fSReza Sabdar 	session->ns_data.dd_env = 0;
19392654012fSReza Sabdar 	session->ns_data.dd_env_len = 0;
19402654012fSReza Sabdar 	session->ns_data.dd_nlist = 0;
19412654012fSReza Sabdar 	session->ns_data.dd_nlist_len = 0;
19422654012fSReza Sabdar 	session->ns_data.dd_mover.addr_type = NDMP_ADDR_LOCAL;
19432654012fSReza Sabdar 	session->ns_data.dd_sock = -1;
19442654012fSReza Sabdar 	session->ns_data.dd_read_offset = 0;
19452654012fSReza Sabdar 	session->ns_data.dd_read_length = 0;
19462654012fSReza Sabdar 	session->ns_data.dd_module.dm_stats.ms_est_bytes_remaining = 0;
19472654012fSReza Sabdar 	session->ns_data.dd_module.dm_stats.ms_est_time_remaining = 0;
19482654012fSReza Sabdar 	/*
19492654012fSReza Sabdar 	 * NDMP V3
19502654012fSReza Sabdar 	 */
19512654012fSReza Sabdar 	session->ns_data.dd_state = NDMP_DATA_STATE_IDLE;
19522654012fSReza Sabdar 	session->ns_data.dd_nlist_v3 = 0;
19532654012fSReza Sabdar 	session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_LOCAL;
19542654012fSReza Sabdar 	session->ns_data.dd_listen_sock = -1;
19552654012fSReza Sabdar 	session->ns_data.dd_bytes_left_to_read = 0LL;
19562654012fSReza Sabdar 	session->ns_data.dd_position = 0LL;
19572654012fSReza Sabdar 	session->ns_data.dd_discard_length = 0LL;
19582654012fSReza Sabdar 	return (0);
19592654012fSReza Sabdar }
19602654012fSReza Sabdar 
19612654012fSReza Sabdar 
19622654012fSReza Sabdar 
19632654012fSReza Sabdar /*
19642654012fSReza Sabdar  * ndmpd_data_cleanup
19652654012fSReza Sabdar  *
19662654012fSReza Sabdar  * Releases resources allocated during a data operation.
19672654012fSReza Sabdar  *
19682654012fSReza Sabdar  * Parameters:
19692654012fSReza Sabdar  *   session (input) - session pointer.
19702654012fSReza Sabdar  *
19712654012fSReza Sabdar  * Returns:
19722654012fSReza Sabdar  *   void
19732654012fSReza Sabdar  */
19742654012fSReza Sabdar void
19752654012fSReza Sabdar ndmpd_data_cleanup(ndmpd_session_t *session)
19762654012fSReza Sabdar {
19772654012fSReza Sabdar 	if (session->ns_data.dd_listen_sock != -1) {
19782654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "data.listen_sock: %d",
19792654012fSReza Sabdar 		    session->ns_data.dd_listen_sock);
19802654012fSReza Sabdar 		(void) ndmpd_remove_file_handler(session,
19812654012fSReza Sabdar 		    session->ns_data.dd_listen_sock);
19822654012fSReza Sabdar 		(void) close(session->ns_data.dd_listen_sock);
19832654012fSReza Sabdar 		session->ns_data.dd_listen_sock = -1;
19842654012fSReza Sabdar 	}
19852654012fSReza Sabdar 	if (session->ns_data.dd_sock != -1) {
19862654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "data.sock: %d",
19872654012fSReza Sabdar 		    session->ns_data.dd_sock);
19882654012fSReza Sabdar 
19892654012fSReza Sabdar 		/*
19902654012fSReza Sabdar 		 * ndmpcopy: we use the same socket for the mover,
19912654012fSReza Sabdar 		 * so expect to close when mover is done!
19922654012fSReza Sabdar 		 */
19932654012fSReza Sabdar 		if (session->ns_data.dd_sock != session->ns_mover.md_sock)
19942654012fSReza Sabdar 			(void) close(session->ns_data.dd_sock);
19952654012fSReza Sabdar 
19962654012fSReza Sabdar 		session->ns_data.dd_sock = -1;
19972654012fSReza Sabdar 	}
19982654012fSReza Sabdar 
19992654012fSReza Sabdar 	ndmpd_free_env(session);
20002654012fSReza Sabdar 	ndmpd_free_nlist(session);
20012654012fSReza Sabdar }
20022654012fSReza Sabdar 
20032654012fSReza Sabdar 
20042654012fSReza Sabdar /*
20052654012fSReza Sabdar  * ndmp_data_get_mover_mode
20062654012fSReza Sabdar  *
20072654012fSReza Sabdar  * Return the mover mode
20082654012fSReza Sabdar  *
20092654012fSReza Sabdar  * Parameters:
20102654012fSReza Sabdar  *   session (input) - session pointer.
20112654012fSReza Sabdar  *
20122654012fSReza Sabdar  * Returns:
20132654012fSReza Sabdar  *   remote - remote backup
20142654012fSReza Sabdar  *   local  - local backup
20152654012fSReza Sabdar  */
20162654012fSReza Sabdar char *
20172654012fSReza Sabdar ndmp_data_get_mover_mode(ndmpd_session_t *session)
20182654012fSReza Sabdar {
20192654012fSReza Sabdar 	char *rv;
20202654012fSReza Sabdar 
20212654012fSReza Sabdar 	switch (session->ns_protocol_version) {
20222654012fSReza Sabdar 	case NDMPV2:
20232654012fSReza Sabdar 		rv = ((session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP)
20242654012fSReza Sabdar 		    ? "remote" : "local");
20252654012fSReza Sabdar 		break;
20262654012fSReza Sabdar 	case NDMPV3:
20272654012fSReza Sabdar 		rv = ((session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_TCP)
20282654012fSReza Sabdar 		    ? "remote" : "local");
20292654012fSReza Sabdar 		break;
20302654012fSReza Sabdar 	case NDMPV4:
20312654012fSReza Sabdar 		rv = ((session->ns_data.dd_data_addr.addr_type ==
20322654012fSReza Sabdar 		    NDMP_ADDR_TCP ||
20332654012fSReza Sabdar 		    (session->ns_data.dd_data_addr_v4.addr_type ==
20342654012fSReza Sabdar 		    NDMP_ADDR_TCP)) ? "remote" : "local");
20352654012fSReza Sabdar 		break;
20362654012fSReza Sabdar 	default:
20378c4f9701SJanice Chang 		rv = "Unknown";
20382654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Invalid protocol version %d.",
20392654012fSReza Sabdar 		    session->ns_protocol_version);
20402654012fSReza Sabdar 	}
20412654012fSReza Sabdar 
20422654012fSReza Sabdar 	return (rv);
20432654012fSReza Sabdar }
20442654012fSReza Sabdar 
20452654012fSReza Sabdar /* *** static functions ******************************************** */
20462654012fSReza Sabdar 
20472654012fSReza Sabdar /*
20488c4f9701SJanice Chang  * ndmpd_tar_start_backup_v2
20492654012fSReza Sabdar  *
20502654012fSReza Sabdar  * Request handling code common to version 1 and
20512654012fSReza Sabdar  * version 2 data_start_backup request handlers.
20522654012fSReza Sabdar  *
20532654012fSReza Sabdar  * Parameters:
20542654012fSReza Sabdar  *   session   (input) - session pointer.
20552654012fSReza Sabdar  *   bu_type   (input) - backup type.
20562654012fSReza Sabdar  *   env_val   (input) - environment variable array.
20572654012fSReza Sabdar  *   env_len   (input) - length of env_val.
20582654012fSReza Sabdar  *
20592654012fSReza Sabdar  * Returns:
20602654012fSReza Sabdar  *   NDMP_NO_ERR - backup successfully started.
20612654012fSReza Sabdar  *   otherwise - error code of backup start error.
20622654012fSReza Sabdar  */
20632654012fSReza Sabdar static ndmp_error
20648c4f9701SJanice Chang ndmpd_tar_start_backup_v2(ndmpd_session_t *session, char *bu_type,
20658c4f9701SJanice Chang     ndmp_pval *env_val, ulong_t env_len)
20662654012fSReza Sabdar {
20672654012fSReza Sabdar 	ndmp_data_start_backup_reply reply;
20682654012fSReza Sabdar 	ndmpd_module_params_t *params;
20692654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
20702654012fSReza Sabdar 	int err;
20712654012fSReza Sabdar 
20722654012fSReza Sabdar 	if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
20732654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Can't start new backup in current state.");
20742654012fSReza Sabdar 		return (NDMP_ILLEGAL_STATE_ERR);
20752654012fSReza Sabdar 	}
20762654012fSReza Sabdar 	if (strcmp(bu_type, NDMP_DUMP_TYPE) != 0 &&
20772654012fSReza Sabdar 	    strcmp(bu_type, NDMP_TAR_TYPE) != 0) {
20782654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Invalid backup type: %s.", bu_type);
20792654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Supported backup types are tar and dump.");
20802654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
20812654012fSReza Sabdar 	}
20822654012fSReza Sabdar 	if ((err = ndmpd_save_env(session, env_val, env_len)) != NDMP_NO_ERR)
20832654012fSReza Sabdar 		return (err);
20842654012fSReza Sabdar 
20852654012fSReza Sabdar 	nlp = ndmp_get_nlp(session);
20862654012fSReza Sabdar 	NDMP_FREE(nlp->nlp_params);
20872654012fSReza Sabdar 	params = nlp->nlp_params = ndmp_malloc(sizeof (ndmpd_module_params_t));
20882654012fSReza Sabdar 	if (params == NULL)
20892654012fSReza Sabdar 		return (NDMP_NO_MEM_ERR);
20902654012fSReza Sabdar 
20912654012fSReza Sabdar 	params->mp_daemon_cookie = (void *)session;
20922654012fSReza Sabdar 	params->mp_module_cookie = &session->ns_data.dd_module.dm_module_cookie;
20932654012fSReza Sabdar 	params->mp_protocol_version = session->ns_protocol_version;
20942654012fSReza Sabdar 	params->mp_operation = NDMP_DATA_OP_BACKUP;
20952654012fSReza Sabdar 	params->mp_get_env_func = ndmpd_api_get_env;
20962654012fSReza Sabdar 	params->mp_add_env_func = ndmpd_api_add_env;
20972654012fSReza Sabdar 	params->mp_get_name_func = ndmpd_api_get_name;
20982654012fSReza Sabdar 	params->mp_dispatch_func = ndmpd_api_dispatch;
20992654012fSReza Sabdar 	params->mp_done_func = ndmpd_api_done_v2;
21002654012fSReza Sabdar 	params->mp_log_func = ndmpd_api_log_v2;
21012654012fSReza Sabdar 	params->mp_add_file_handler_func = ndmpd_api_add_file_handler;
21022654012fSReza Sabdar 	params->mp_remove_file_handler_func = ndmpd_api_remove_file_handler;
21032654012fSReza Sabdar 	params->mp_write_func = ndmpd_api_write_v2;
21042654012fSReza Sabdar 	params->mp_read_func = 0;
21052654012fSReza Sabdar 	params->mp_file_recovered_func = 0;
21062654012fSReza Sabdar 	params->mp_stats = &session->ns_data.dd_module.dm_stats;
21072654012fSReza Sabdar 
21082654012fSReza Sabdar 	session->ns_data.dd_module.dm_module_cookie = 0;
21092654012fSReza Sabdar 	if (strcmp(bu_type, NDMP_DUMP_TYPE) == 0) {
21102654012fSReza Sabdar 		NLP_SET(nlp, NLPF_DUMP);
21112654012fSReza Sabdar 		params->mp_file_history_path_func = 0;
21122654012fSReza Sabdar 		params->mp_file_history_dir_func =
21132654012fSReza Sabdar 		    ndmpd_api_file_history_dir_v2;
21142654012fSReza Sabdar 		params->mp_file_history_node_func =
21152654012fSReza Sabdar 		    ndmpd_api_file_history_node_v2;
21162654012fSReza Sabdar 	} else if (strcmp(bu_type, NDMP_TAR_TYPE) == 0) {
21172654012fSReza Sabdar 		/* backup type == NDMP_TAR_TYPE */
21182654012fSReza Sabdar 		NLP_SET(nlp, NLPF_TAR);
21192654012fSReza Sabdar 		params->mp_file_history_path_func =
21202654012fSReza Sabdar 		    ndmpd_api_file_history_path_v2;
21212654012fSReza Sabdar 		params->mp_file_history_dir_func = 0;
21222654012fSReza Sabdar 		params->mp_file_history_node_func = 0;
21232654012fSReza Sabdar 	} else {
21242654012fSReza Sabdar 		NLP_UNSET(nlp, NLPF_DUMP);
21252654012fSReza Sabdar 		NLP_UNSET(nlp, NLPF_TAR);
21262654012fSReza Sabdar 	}
21272654012fSReza Sabdar 
21282654012fSReza Sabdar 	session->ns_data.dd_module.dm_start_func = ndmpd_tar_backup_starter;
21292654012fSReza Sabdar 	session->ns_data.dd_module.dm_abort_func = ndmpd_tar_backup_abort;
21302654012fSReza Sabdar 
21312654012fSReza Sabdar 	session->ns_data.dd_module.dm_stats.ms_est_bytes_remaining = 0;
21322654012fSReza Sabdar 	session->ns_data.dd_module.dm_stats.ms_est_time_remaining = 0;
21332654012fSReza Sabdar 	session->ns_data.dd_nlist = 0;
21342654012fSReza Sabdar 	session->ns_data.dd_nlist_len = 0;
21352654012fSReza Sabdar 	session->ns_data.dd_read_offset = 0;
21362654012fSReza Sabdar 	session->ns_data.dd_read_length = 0;
21372654012fSReza Sabdar 
21382654012fSReza Sabdar 	if ((err = ndmp_backup_extract_params(session,
21392654012fSReza Sabdar 	    params)) != NDMP_NO_ERR) {
21402654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "err: %d", err);
21412654012fSReza Sabdar 		NDMP_FREE(nlp->nlp_params);
21422654012fSReza Sabdar 		return (err);
21432654012fSReza Sabdar 	}
21442654012fSReza Sabdar 
21452654012fSReza Sabdar 	err = ndmpd_mover_connect(session, NDMP_MOVER_MODE_READ);
21462654012fSReza Sabdar 	if (err != NDMP_NO_ERR) {
21472654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
21482654012fSReza Sabdar 		    "mover connect err: %d", err);
21492654012fSReza Sabdar 		NDMP_FREE(nlp->nlp_params);
21502654012fSReza Sabdar 		return (err);
21512654012fSReza Sabdar 	}
21522654012fSReza Sabdar 
21532654012fSReza Sabdar 	session->ns_data.dd_state = NDMP_DATA_STATE_ACTIVE;
21542654012fSReza Sabdar 
21552654012fSReza Sabdar 	session->ns_data.dd_operation = NDMP_DATA_OP_BACKUP;
21562654012fSReza Sabdar 	session->ns_data.dd_abort = FALSE;
21572654012fSReza Sabdar 
21582654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "starting backup");
21592654012fSReza Sabdar 
21602654012fSReza Sabdar 	reply.error = NDMP_NO_ERR;
21612654012fSReza Sabdar 	if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
21622654012fSReza Sabdar 	    &reply) < 0) {
21632654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Sending data_start_backup reply");
21642654012fSReza Sabdar 		NDMP_FREE(nlp->nlp_params);
21652654012fSReza Sabdar 		if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
21662654012fSReza Sabdar 			/*
21672654012fSReza Sabdar 			 * ndmpcopy: we use the same socket for the mover,
21682654012fSReza Sabdar 			 * so expect to close when mover is done!
21692654012fSReza Sabdar 			 */
21702654012fSReza Sabdar 			if (session->ns_data.dd_sock !=
21712654012fSReza Sabdar 			    session->ns_mover.md_sock)
21722654012fSReza Sabdar 				(void) close(session->ns_data.dd_sock);
21732654012fSReza Sabdar 
21742654012fSReza Sabdar 			session->ns_data.dd_sock = -1;
21752654012fSReza Sabdar 		} else
21762654012fSReza Sabdar 			ndmpd_mover_error(session,
21772654012fSReza Sabdar 			    NDMP_MOVER_HALT_CONNECT_CLOSED);
21782654012fSReza Sabdar 		return (NDMP_NO_ERR);
21792654012fSReza Sabdar 	}
21802654012fSReza Sabdar 
21812654012fSReza Sabdar 	/*
21822654012fSReza Sabdar 	 * perform the backup
21832654012fSReza Sabdar 	 *
21842654012fSReza Sabdar 	 * Cannot wait for the thread to exit as we are replying to the
21852654012fSReza Sabdar 	 * client request here.
21862654012fSReza Sabdar 	 */
21872654012fSReza Sabdar 	(void) pthread_create(NULL, NULL,
21882654012fSReza Sabdar 	    (funct_t)session->ns_data.dd_module.dm_start_func,
21892654012fSReza Sabdar 	    params);
21902654012fSReza Sabdar 
21912654012fSReza Sabdar 	return (NDMP_NO_ERR);
21922654012fSReza Sabdar }
21932654012fSReza Sabdar 
21942654012fSReza Sabdar /*
21958c4f9701SJanice Chang  * ndmpd_tar_start_recover_v2
21962654012fSReza Sabdar  *
21972654012fSReza Sabdar  * The main recover/restore function
21982654012fSReza Sabdar  *
21992654012fSReza Sabdar  * Parameters:
22002654012fSReza Sabdar  *   session   (input) - session pointer.
22012654012fSReza Sabdar  *   bu_type   (input) - backup type.
22022654012fSReza Sabdar  *   env_val   (input) - environment variable array.
22032654012fSReza Sabdar  *   env_len   (input) - length of env_val.
22048c4f9701SJanice Chang  *   nlist_val (input) - list of files.
22058c4f9701SJanice Chang  *   nlist_len (input) - length of nlist_val.
22062654012fSReza Sabdar  *
22072654012fSReza Sabdar  * Returns:
22082654012fSReza Sabdar  *   NDMP_NO_ERR - recover successfully started.
22092654012fSReza Sabdar  *   otherwise - error code of backup start error.
22102654012fSReza Sabdar  */
22112654012fSReza Sabdar static ndmp_error
22128c4f9701SJanice Chang ndmpd_tar_start_recover_v2(ndmpd_session_t *session, char *bu_type,
22138c4f9701SJanice Chang     ndmp_pval *env_val, ulong_t env_len, ndmp_name *nlist_val,
22148c4f9701SJanice Chang     ulong_t nlist_len)
22152654012fSReza Sabdar {
22162654012fSReza Sabdar 	ndmp_data_start_recover_reply_v2 reply;
22172654012fSReza Sabdar 	ndmpd_module_params_t *params;
22182654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
22192654012fSReza Sabdar 	int err;
22202654012fSReza Sabdar 
22212654012fSReza Sabdar 	if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
22222654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Can't start new recover in current state.");
22232654012fSReza Sabdar 		return (NDMP_ILLEGAL_STATE_ERR);
22242654012fSReza Sabdar 	}
22252654012fSReza Sabdar 
22262654012fSReza Sabdar 	if (strcmp(bu_type, NDMP_DUMP_TYPE) != 0 &&
22272654012fSReza Sabdar 	    strcmp(bu_type, NDMP_TAR_TYPE) != 0) {
22282654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Invalid backup type: %s.", bu_type);
22292654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Supported backup types are tar and dump.");
22302654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
22312654012fSReza Sabdar 	}
22322654012fSReza Sabdar 
22332654012fSReza Sabdar 	reply.error = ndmpd_save_env(session, env_val, env_len);
22342654012fSReza Sabdar 	if (reply.error != NDMP_NO_ERR)
22352654012fSReza Sabdar 		return (NDMP_NO_MEM_ERR);
22362654012fSReza Sabdar 
22372654012fSReza Sabdar 	reply.error = ndmpd_save_nlist_v2(session, nlist_val, nlist_len);
22382654012fSReza Sabdar 	if (reply.error != NDMP_NO_ERR)
22392654012fSReza Sabdar 		return (NDMP_NO_MEM_ERR);
22402654012fSReza Sabdar 
22412654012fSReza Sabdar 	nlp = ndmp_get_nlp(session);
22422654012fSReza Sabdar 	NDMP_FREE(nlp->nlp_params);
22432654012fSReza Sabdar 	params = nlp->nlp_params = ndmp_malloc(sizeof (ndmpd_module_params_t));
22442654012fSReza Sabdar 	if (params == NULL)
22452654012fSReza Sabdar 		return (NDMP_NO_MEM_ERR);
22462654012fSReza Sabdar 
22472654012fSReza Sabdar 	/*
22482654012fSReza Sabdar 	 * Setup restore parameters.
22492654012fSReza Sabdar 	 */
22502654012fSReza Sabdar 	params->mp_daemon_cookie = (void *)session;
22512654012fSReza Sabdar 	params->mp_module_cookie = &session->ns_data.dd_module.dm_module_cookie;
22522654012fSReza Sabdar 	params->mp_protocol_version = session->ns_protocol_version;
22532654012fSReza Sabdar 	params->mp_operation = NDMP_DATA_OP_RECOVER;
22542654012fSReza Sabdar 	params->mp_get_env_func = ndmpd_api_get_env;
22552654012fSReza Sabdar 	params->mp_add_env_func = ndmpd_api_add_env;
22562654012fSReza Sabdar 	params->mp_get_name_func = ndmpd_api_get_name;
22572654012fSReza Sabdar 	params->mp_dispatch_func = ndmpd_api_dispatch;
22582654012fSReza Sabdar 	params->mp_done_func = ndmpd_api_done_v2;
22592654012fSReza Sabdar 	params->mp_log_func = ndmpd_api_log_v2;
22602654012fSReza Sabdar 	params->mp_add_file_handler_func = ndmpd_api_add_file_handler;
22612654012fSReza Sabdar 	params->mp_remove_file_handler_func = ndmpd_api_remove_file_handler;
22622654012fSReza Sabdar 	params->mp_write_func = 0;
22632654012fSReza Sabdar 	params->mp_file_history_path_func = 0;
22642654012fSReza Sabdar 	params->mp_file_history_dir_func = 0;
22652654012fSReza Sabdar 	params->mp_file_history_node_func = 0;
22662654012fSReza Sabdar 	params->mp_read_func = ndmpd_api_read_v2;
22672654012fSReza Sabdar 	params->mp_seek_func = ndmpd_api_seek_v2;
22682654012fSReza Sabdar 	params->mp_file_recovered_func = ndmpd_api_file_recovered_v2;
22692654012fSReza Sabdar 	params->mp_stats = &session->ns_data.dd_module.dm_stats;
22702654012fSReza Sabdar 
22712654012fSReza Sabdar 	session->ns_data.dd_module.dm_module_cookie = 0;
22722654012fSReza Sabdar 	session->ns_data.dd_module.dm_start_func = ndmpd_tar_restore_starter;
22732654012fSReza Sabdar 	session->ns_data.dd_module.dm_abort_func = ndmpd_tar_restore_abort;
22742654012fSReza Sabdar 	session->ns_data.dd_module.dm_stats.ms_est_bytes_remaining = 0;
22752654012fSReza Sabdar 	session->ns_data.dd_module.dm_stats.ms_est_time_remaining = 0;
22762654012fSReza Sabdar 	session->ns_data.dd_read_offset = 0;
22772654012fSReza Sabdar 	session->ns_data.dd_read_length = 0;
22782654012fSReza Sabdar 
22792654012fSReza Sabdar 	if ((err = ndmp_restore_extract_params(session,
22802654012fSReza Sabdar 	    params)) != NDMP_NO_ERR) {
22812654012fSReza Sabdar 		NDMP_FREE(nlp->nlp_params);
22822654012fSReza Sabdar 		return (err);
22832654012fSReza Sabdar 	}
22842654012fSReza Sabdar 
22852654012fSReza Sabdar 	err = ndmpd_mover_connect(session, NDMP_MOVER_MODE_WRITE);
22862654012fSReza Sabdar 	if (err != NDMP_NO_ERR) {
22872654012fSReza Sabdar 		NDMP_FREE(nlp->nlp_params);
22882654012fSReza Sabdar 		return (err);
22892654012fSReza Sabdar 	}
22902654012fSReza Sabdar 
22912654012fSReza Sabdar 	session->ns_data.dd_state = NDMP_DATA_STATE_ACTIVE;
22922654012fSReza Sabdar 	session->ns_data.dd_operation = NDMP_DATA_OP_RECOVER;
22932654012fSReza Sabdar 	session->ns_data.dd_abort = FALSE;
22942654012fSReza Sabdar 
22952654012fSReza Sabdar 	reply.error = NDMP_NO_ERR;
22962654012fSReza Sabdar 	if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
22972654012fSReza Sabdar 	    &reply) < 0) {
22982654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Sending data_start_recover reply");
22992654012fSReza Sabdar 		NDMP_FREE(nlp->nlp_params);
23002654012fSReza Sabdar 		if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
23012654012fSReza Sabdar 			/*
23022654012fSReza Sabdar 			 * ndmpcopy: we use the same socket for the mover,
23032654012fSReza Sabdar 			 * so expect to close when mover is done!
23042654012fSReza Sabdar 			 */
23052654012fSReza Sabdar 			if (session->ns_data.dd_sock !=
23062654012fSReza Sabdar 			    session->ns_mover.md_sock)
23072654012fSReza Sabdar 				(void) close(session->ns_data.dd_sock);
23082654012fSReza Sabdar 
23092654012fSReza Sabdar 			session->ns_data.dd_sock = -1;
23102654012fSReza Sabdar 		} else {
23112654012fSReza Sabdar 			ndmpd_mover_error(session,
23122654012fSReza Sabdar 			    NDMP_MOVER_HALT_CONNECT_CLOSED);
23132654012fSReza Sabdar 		}
23142654012fSReza Sabdar 		return (NDMP_NO_ERR);
23152654012fSReza Sabdar 	}
23162654012fSReza Sabdar 
23172654012fSReza Sabdar 
23182654012fSReza Sabdar 	/*
23192654012fSReza Sabdar 	 * perform the restore
23202654012fSReza Sabdar 	 *
23218c4f9701SJanice Chang 	 * Cannot wait for the thread to exit as we are replying to the
23222654012fSReza Sabdar 	 * client request here.
23232654012fSReza Sabdar 	 */
23242654012fSReza Sabdar 	(void) pthread_create(NULL, NULL,
23252654012fSReza Sabdar 	    (funct_t)session->ns_data.dd_module.dm_start_func,
23262654012fSReza Sabdar 	    params);
23272654012fSReza Sabdar 
23282654012fSReza Sabdar 	return (NDMP_NO_ERR);
23292654012fSReza Sabdar }
23302654012fSReza Sabdar 
23312654012fSReza Sabdar /*
23322654012fSReza Sabdar  * ndmpd_data_get_info
23332654012fSReza Sabdar  *
23342654012fSReza Sabdar  * Return the total number of bytes processed
23352654012fSReza Sabdar  *
23362654012fSReza Sabdar  * Parameters:
23372654012fSReza Sabdar  *   session   (input) - session pointer.
23382654012fSReza Sabdar  *
23392654012fSReza Sabdar  * Returns:
23402654012fSReza Sabdar  *   the number of bytes processed
23412654012fSReza Sabdar  */
23422654012fSReza Sabdar static u_longlong_t
23432654012fSReza Sabdar ndmpd_data_get_info(ndmpd_session_t *session)
23442654012fSReza Sabdar {
23452654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
23462654012fSReza Sabdar 
23472654012fSReza Sabdar 	nlp = ndmp_get_nlp(session);
23482654012fSReza Sabdar 	if (nlp == NULL)
23492654012fSReza Sabdar 		return ((u_longlong_t)0);
23502654012fSReza Sabdar 
23512654012fSReza Sabdar 	if (nlp->nlp_jstat == NULL)
23522654012fSReza Sabdar 		return (nlp->nlp_bytes_total);
23532654012fSReza Sabdar 
23542654012fSReza Sabdar 	return ((u_longlong_t)nlp->nlp_jstat->js_bytes_total);
23552654012fSReza Sabdar }
2356