xref: /onnv-gate/usr/src/cmd/ndmpd/ndmp/ndmpd_data.c (revision 8193:9b3c96bc17e3)
17917SReza.Sabdar@Sun.COM /*
27917SReza.Sabdar@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
37917SReza.Sabdar@Sun.COM  * Use is subject to license terms.
47917SReza.Sabdar@Sun.COM  */
57917SReza.Sabdar@Sun.COM 
67917SReza.Sabdar@Sun.COM /*
77917SReza.Sabdar@Sun.COM  * BSD 3 Clause License
87917SReza.Sabdar@Sun.COM  *
97917SReza.Sabdar@Sun.COM  * Copyright (c) 2007, The Storage Networking Industry Association.
107917SReza.Sabdar@Sun.COM  *
117917SReza.Sabdar@Sun.COM  * Redistribution and use in source and binary forms, with or without
127917SReza.Sabdar@Sun.COM  * modification, are permitted provided that the following conditions
137917SReza.Sabdar@Sun.COM  * are met:
147917SReza.Sabdar@Sun.COM  * 	- Redistributions of source code must retain the above copyright
157917SReza.Sabdar@Sun.COM  *	  notice, this list of conditions and the following disclaimer.
167917SReza.Sabdar@Sun.COM  *
177917SReza.Sabdar@Sun.COM  * 	- Redistributions in binary form must reproduce the above copyright
187917SReza.Sabdar@Sun.COM  *	  notice, this list of conditions and the following disclaimer in
197917SReza.Sabdar@Sun.COM  *	  the documentation and/or other materials provided with the
207917SReza.Sabdar@Sun.COM  *	  distribution.
217917SReza.Sabdar@Sun.COM  *
227917SReza.Sabdar@Sun.COM  *	- Neither the name of The Storage Networking Industry Association (SNIA)
237917SReza.Sabdar@Sun.COM  *	  nor the names of its contributors may be used to endorse or promote
247917SReza.Sabdar@Sun.COM  *	  products derived from this software without specific prior written
257917SReza.Sabdar@Sun.COM  *	  permission.
267917SReza.Sabdar@Sun.COM  *
277917SReza.Sabdar@Sun.COM  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
287917SReza.Sabdar@Sun.COM  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
297917SReza.Sabdar@Sun.COM  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
307917SReza.Sabdar@Sun.COM  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
317917SReza.Sabdar@Sun.COM  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
327917SReza.Sabdar@Sun.COM  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
337917SReza.Sabdar@Sun.COM  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
347917SReza.Sabdar@Sun.COM  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
357917SReza.Sabdar@Sun.COM  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
367917SReza.Sabdar@Sun.COM  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
377917SReza.Sabdar@Sun.COM  * POSSIBILITY OF SUCH DAMAGE.
387917SReza.Sabdar@Sun.COM  */
397917SReza.Sabdar@Sun.COM /* Copyright (c) 2007, The Storage Networking Industry Association. */
407917SReza.Sabdar@Sun.COM /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
417917SReza.Sabdar@Sun.COM #include <sys/types.h>
427917SReza.Sabdar@Sun.COM #include <sys/param.h>
437917SReza.Sabdar@Sun.COM #include <sys/socket.h>
447917SReza.Sabdar@Sun.COM #include <netinet/in.h>
457917SReza.Sabdar@Sun.COM #include <errno.h>
467917SReza.Sabdar@Sun.COM #include <arpa/inet.h>
477917SReza.Sabdar@Sun.COM #include <stdlib.h>
487917SReza.Sabdar@Sun.COM #include <string.h>
497917SReza.Sabdar@Sun.COM #include "ndmpd_common.h"
507917SReza.Sabdar@Sun.COM #include "ndmpd.h"
517917SReza.Sabdar@Sun.COM 
527917SReza.Sabdar@Sun.COM static int ndmpd_data_error_send_v4(ndmpd_session_t *session,
537917SReza.Sabdar@Sun.COM     ndmp_data_halt_reason reason);
547917SReza.Sabdar@Sun.COM static int ndmpd_data_error_send(ndmpd_session_t *session,
557917SReza.Sabdar@Sun.COM     ndmp_data_halt_reason reason);
567917SReza.Sabdar@Sun.COM static void data_accept_connection_v3(void *cookie, int fd, ulong_t mode);
577917SReza.Sabdar@Sun.COM static int create_listen_socket_v3(ndmpd_session_t *session, ulong_t *addr,
587917SReza.Sabdar@Sun.COM     ushort_t *port);
597917SReza.Sabdar@Sun.COM static ndmp_error data_connect_sock_v3(ndmpd_session_t *session, ulong_t addr,
607917SReza.Sabdar@Sun.COM     ushort_t port);
617917SReza.Sabdar@Sun.COM static int discard_data_v3(ndmpd_session_t *session, ulong_t length);
627917SReza.Sabdar@Sun.COM static void nlp_release_job_stat(ndmpd_session_t *session);
637917SReza.Sabdar@Sun.COM static u_longlong_t ndmpd_data_get_info(ndmpd_session_t *session);
647917SReza.Sabdar@Sun.COM static ndmp_error start_backup_v3(ndmpd_session_t *session, char *bu_type,
657917SReza.Sabdar@Sun.COM     ndmp_pval *env_val, ulong_t env_len);
667917SReza.Sabdar@Sun.COM static ndmp_error start_backup(ndmpd_session_t *session, char *bu_type,
677917SReza.Sabdar@Sun.COM     ndmp_pval *env_val, ulong_t env_len);
687917SReza.Sabdar@Sun.COM static ndmp_error start_recover(ndmpd_session_t *session, char *bu_type,
697917SReza.Sabdar@Sun.COM     ndmp_pval *env_val, ulong_t env_len, ndmp_name *nlist_val,
707917SReza.Sabdar@Sun.COM     ulong_t nlist_len);
717917SReza.Sabdar@Sun.COM static ndmp_error start_recover_v3(ndmpd_session_t *session, char *bu_type,
727917SReza.Sabdar@Sun.COM     ndmp_pval *env_val, ulong_t env_len, ndmp_name_v3 *nlist_val,
737917SReza.Sabdar@Sun.COM     ulong_t nlist_len);
747917SReza.Sabdar@Sun.COM static ndmp_error start_backup(ndmpd_session_t *session, char *bu_type,
757917SReza.Sabdar@Sun.COM     ndmp_pval *env_val, ulong_t env_len);
767917SReza.Sabdar@Sun.COM static ndmp_error start_recover(ndmpd_session_t *session, char *bu_type,
777917SReza.Sabdar@Sun.COM     ndmp_pval *env_val, ulong_t env_len, ndmp_name *nlist_val,
787917SReza.Sabdar@Sun.COM     ulong_t nlist_len);
797917SReza.Sabdar@Sun.COM static u_longlong_t ndmpd_data_get_info(ndmpd_session_t *session);
807917SReza.Sabdar@Sun.COM static void nlp_release_job_stat(ndmpd_session_t *session);
817917SReza.Sabdar@Sun.COM 
827917SReza.Sabdar@Sun.COM 
837917SReza.Sabdar@Sun.COM /*
847917SReza.Sabdar@Sun.COM  * ************************************************************************
857917SReza.Sabdar@Sun.COM  * NDMP V2 HANDLERS
867917SReza.Sabdar@Sun.COM  * ************************************************************************
877917SReza.Sabdar@Sun.COM  */
887917SReza.Sabdar@Sun.COM 
897917SReza.Sabdar@Sun.COM /*
907917SReza.Sabdar@Sun.COM  * ndmpd_data_get_state_v2
917917SReza.Sabdar@Sun.COM  *
927917SReza.Sabdar@Sun.COM  * Request handler. Returns current data state.
937917SReza.Sabdar@Sun.COM  *
947917SReza.Sabdar@Sun.COM  * Parameters:
957917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
967917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
977917SReza.Sabdar@Sun.COM  *
987917SReza.Sabdar@Sun.COM  * Returns:
997917SReza.Sabdar@Sun.COM  *   void
1007917SReza.Sabdar@Sun.COM  */
1017917SReza.Sabdar@Sun.COM /*ARGSUSED*/
1027917SReza.Sabdar@Sun.COM void
1037917SReza.Sabdar@Sun.COM ndmpd_data_get_state_v2(ndmp_connection_t *connection, void *body)
1047917SReza.Sabdar@Sun.COM {
1057917SReza.Sabdar@Sun.COM 	ndmp_data_get_state_reply_v2 reply;
1067917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
1077917SReza.Sabdar@Sun.COM 
1087917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
1097917SReza.Sabdar@Sun.COM 	reply.operation = session->ns_data.dd_operation;
1107917SReza.Sabdar@Sun.COM 	reply.state = session->ns_data.dd_state;
1117917SReza.Sabdar@Sun.COM 	reply.halt_reason = session->ns_data.dd_halt_reason;
1127917SReza.Sabdar@Sun.COM 
1137917SReza.Sabdar@Sun.COM 	reply.est_time_remain =
1147917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_module.dm_stats.ms_est_time_remaining;
1157917SReza.Sabdar@Sun.COM 	reply.est_bytes_remain =
1167917SReza.Sabdar@Sun.COM 	    long_long_to_quad(
1177917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_module.dm_stats.ms_est_bytes_remaining);
1187917SReza.Sabdar@Sun.COM 
1197917SReza.Sabdar@Sun.COM 	reply.bytes_processed =
1207917SReza.Sabdar@Sun.COM 	    long_long_to_quad(ndmpd_data_get_info(session));
1217917SReza.Sabdar@Sun.COM 
1227917SReza.Sabdar@Sun.COM 	reply.mover = session->ns_data.dd_mover;
1237917SReza.Sabdar@Sun.COM 	reply.read_offset = long_long_to_quad(session->ns_data.dd_read_offset);
1247917SReza.Sabdar@Sun.COM 	reply.read_length = long_long_to_quad(session->ns_data.dd_read_length);
1257917SReza.Sabdar@Sun.COM 
1267917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
1277917SReza.Sabdar@Sun.COM 	    "sending data_get_state reply");
1287917SReza.Sabdar@Sun.COM }
1297917SReza.Sabdar@Sun.COM 
1307917SReza.Sabdar@Sun.COM 
1317917SReza.Sabdar@Sun.COM /*
1327917SReza.Sabdar@Sun.COM  * ndmpd_data_start_backup_v2
1337917SReza.Sabdar@Sun.COM  *
1347917SReza.Sabdar@Sun.COM  * Request handler. Starts a backup.
1357917SReza.Sabdar@Sun.COM  *
1367917SReza.Sabdar@Sun.COM  * Parameters:
1377917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
1387917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
1397917SReza.Sabdar@Sun.COM  *
1407917SReza.Sabdar@Sun.COM  * Returns:
1417917SReza.Sabdar@Sun.COM  *   void
1427917SReza.Sabdar@Sun.COM  */
1437917SReza.Sabdar@Sun.COM void
1447917SReza.Sabdar@Sun.COM ndmpd_data_start_backup_v2(ndmp_connection_t *connection, void *body)
1457917SReza.Sabdar@Sun.COM {
1467917SReza.Sabdar@Sun.COM 	ndmp_data_start_backup_request_v2 *request;
1477917SReza.Sabdar@Sun.COM 	ndmp_data_start_backup_reply_v2 reply;
1487917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
1497917SReza.Sabdar@Sun.COM 	ndmp_error err;
1507917SReza.Sabdar@Sun.COM 
1517917SReza.Sabdar@Sun.COM 	request = (ndmp_data_start_backup_request_v2 *)body;
1527917SReza.Sabdar@Sun.COM 
1537917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
1547917SReza.Sabdar@Sun.COM 	session->ns_data.dd_mover = request->mover;
1557917SReza.Sabdar@Sun.COM 
1567917SReza.Sabdar@Sun.COM 	err = start_backup(session, request->bu_type, request->env.env_val,
1577917SReza.Sabdar@Sun.COM 	    request->env.env_len);
1587917SReza.Sabdar@Sun.COM 
1597917SReza.Sabdar@Sun.COM 	/*
1607917SReza.Sabdar@Sun.COM 	 * start_backup sends the reply if the backup is successfully started.
1617917SReza.Sabdar@Sun.COM 	 * Otherwise, send the reply containing the error here.
1627917SReza.Sabdar@Sun.COM 	 */
1637917SReza.Sabdar@Sun.COM 	if (err != NDMP_NO_ERR) {
1647917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "err: %d", err);
1657917SReza.Sabdar@Sun.COM 		reply.error = err;
1667917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
1677917SReza.Sabdar@Sun.COM 		    "sending data_start_backup reply");
1687917SReza.Sabdar@Sun.COM 		ndmpd_data_cleanup(session);
1697917SReza.Sabdar@Sun.COM 	}
1707917SReza.Sabdar@Sun.COM }
1717917SReza.Sabdar@Sun.COM 
1727917SReza.Sabdar@Sun.COM 
1737917SReza.Sabdar@Sun.COM /*
1747917SReza.Sabdar@Sun.COM  * ndmpd_data_start_recover_v2
1757917SReza.Sabdar@Sun.COM  *
1767917SReza.Sabdar@Sun.COM  * Request handler. Starts a restore.
1777917SReza.Sabdar@Sun.COM  *
1787917SReza.Sabdar@Sun.COM  * Parameters:
1797917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
1807917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
1817917SReza.Sabdar@Sun.COM  *
1827917SReza.Sabdar@Sun.COM  * Returns:
1837917SReza.Sabdar@Sun.COM  *   void
1847917SReza.Sabdar@Sun.COM  */
1857917SReza.Sabdar@Sun.COM void
1867917SReza.Sabdar@Sun.COM ndmpd_data_start_recover_v2(ndmp_connection_t *connection, void *body)
1877917SReza.Sabdar@Sun.COM {
1887917SReza.Sabdar@Sun.COM 	ndmp_data_start_recover_request_v2 *request;
1897917SReza.Sabdar@Sun.COM 	ndmp_data_start_recover_reply_v2 reply;
1907917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
1917917SReza.Sabdar@Sun.COM 	ndmp_error err;
1927917SReza.Sabdar@Sun.COM 
1937917SReza.Sabdar@Sun.COM 	request = (ndmp_data_start_recover_request_v2 *) body;
1947917SReza.Sabdar@Sun.COM 	session->ns_data.dd_mover = request->mover;
1957917SReza.Sabdar@Sun.COM 
1967917SReza.Sabdar@Sun.COM 	err = start_recover(session, request->bu_type, request->env.env_val,
1977917SReza.Sabdar@Sun.COM 	    request->env.env_len, request->nlist.nlist_val,
1987917SReza.Sabdar@Sun.COM 	    request->nlist.nlist_len);
1997917SReza.Sabdar@Sun.COM 	/*
2007917SReza.Sabdar@Sun.COM 	 * start_recover sends the reply if the recover is successfully started.
2017917SReza.Sabdar@Sun.COM 	 * Otherwise, send the reply containing the error here.
2027917SReza.Sabdar@Sun.COM 	 */
2037917SReza.Sabdar@Sun.COM 	if (err != NDMP_NO_ERR) {
2047917SReza.Sabdar@Sun.COM 		reply.error = err;
2057917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
2067917SReza.Sabdar@Sun.COM 		    "sending ndmp_data_start_recover_request_v2 reply");
2077917SReza.Sabdar@Sun.COM 		ndmpd_data_cleanup(session);
2087917SReza.Sabdar@Sun.COM 	}
2097917SReza.Sabdar@Sun.COM }
2107917SReza.Sabdar@Sun.COM 
2117917SReza.Sabdar@Sun.COM 
2127917SReza.Sabdar@Sun.COM /*
2137917SReza.Sabdar@Sun.COM  * ndmpd_data_get_env_v2
2147917SReza.Sabdar@Sun.COM  *
2157917SReza.Sabdar@Sun.COM  * Request handler. Returns the environment variable array sent
2167917SReza.Sabdar@Sun.COM  * with the backup request. This request may only be sent with
2177917SReza.Sabdar@Sun.COM  * a backup operation is in progress.
2187917SReza.Sabdar@Sun.COM  *
2197917SReza.Sabdar@Sun.COM  * Parameters:
2207917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
2217917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
2227917SReza.Sabdar@Sun.COM  *
2237917SReza.Sabdar@Sun.COM  * Returns:
2247917SReza.Sabdar@Sun.COM  *   void
2257917SReza.Sabdar@Sun.COM  */
2267917SReza.Sabdar@Sun.COM /*ARGSUSED*/
2277917SReza.Sabdar@Sun.COM void
2287917SReza.Sabdar@Sun.COM ndmpd_data_get_env_v2(ndmp_connection_t *connection, void *body)
2297917SReza.Sabdar@Sun.COM {
2307917SReza.Sabdar@Sun.COM 	ndmp_data_get_env_reply reply;
2317917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
2327917SReza.Sabdar@Sun.COM 
2337917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
2347917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_operation != NDMP_DATA_OP_BACKUP) {
2357917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Backup operation not active.");
2367917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
2377917SReza.Sabdar@Sun.COM 		reply.env.env_len = 0;
2387917SReza.Sabdar@Sun.COM 	} else {
2397917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
2407917SReza.Sabdar@Sun.COM 		reply.env.env_len = session->ns_data.dd_env_len;
2417917SReza.Sabdar@Sun.COM 		reply.env.env_val = session->ns_data.dd_env;
2427917SReza.Sabdar@Sun.COM 	}
2437917SReza.Sabdar@Sun.COM 
2447917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply, "sending data_get_env reply");
2457917SReza.Sabdar@Sun.COM }
2467917SReza.Sabdar@Sun.COM 
2477917SReza.Sabdar@Sun.COM 
2487917SReza.Sabdar@Sun.COM /*
2497917SReza.Sabdar@Sun.COM  * ndmpd_data_stop_v2
2507917SReza.Sabdar@Sun.COM  *
2517917SReza.Sabdar@Sun.COM  * Request handler. Stops the current data operation.
2527917SReza.Sabdar@Sun.COM  *
2537917SReza.Sabdar@Sun.COM  * Parameters:
2547917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
2557917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
2567917SReza.Sabdar@Sun.COM  *
2577917SReza.Sabdar@Sun.COM  * Returns:
2587917SReza.Sabdar@Sun.COM  *   void
2597917SReza.Sabdar@Sun.COM  */
2607917SReza.Sabdar@Sun.COM /*ARGSUSED*/
2617917SReza.Sabdar@Sun.COM void
2627917SReza.Sabdar@Sun.COM ndmpd_data_stop_v2(ndmp_connection_t *connection, void *body)
2637917SReza.Sabdar@Sun.COM {
2647917SReza.Sabdar@Sun.COM 	ndmp_data_stop_reply reply;
2657917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
2667917SReza.Sabdar@Sun.COM 
2677917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_HALTED) {
2687917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid state to process stop request.");
2697917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
2707917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
2717917SReza.Sabdar@Sun.COM 		    "sending data_stop reply");
2727917SReza.Sabdar@Sun.COM 		return;
2737917SReza.Sabdar@Sun.COM 	}
2747917SReza.Sabdar@Sun.COM 	ndmp_waitfor_op(session);
2757917SReza.Sabdar@Sun.COM 	ndmpd_data_cleanup(session);
2767917SReza.Sabdar@Sun.COM 	ndmpd_file_history_cleanup(session, FALSE);
2777917SReza.Sabdar@Sun.COM 
2787917SReza.Sabdar@Sun.COM 	nlp_release_job_stat(session);
2797917SReza.Sabdar@Sun.COM 
2807917SReza.Sabdar@Sun.COM 	/* prepare for another data operation */
2817917SReza.Sabdar@Sun.COM 	(void) ndmpd_data_init(session);
2827917SReza.Sabdar@Sun.COM 	ndmpd_file_history_init(session);
2837917SReza.Sabdar@Sun.COM 
2847917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
2857917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply, "sending data_stop reply");
2867917SReza.Sabdar@Sun.COM }
2877917SReza.Sabdar@Sun.COM 
2887917SReza.Sabdar@Sun.COM 
2897917SReza.Sabdar@Sun.COM /*
2907917SReza.Sabdar@Sun.COM  * ndmpd_data_abort_v2
2917917SReza.Sabdar@Sun.COM  *
2927917SReza.Sabdar@Sun.COM  * Request handler. Aborts the current backup/restore. The operation
2937917SReza.Sabdar@Sun.COM  * state is not changed to the halted state until after the operation
2947917SReza.Sabdar@Sun.COM  * has actually been aborted and the notify_halt request has been sent.
2957917SReza.Sabdar@Sun.COM  *
2967917SReza.Sabdar@Sun.COM  * Parameters:
2977917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
2987917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
2997917SReza.Sabdar@Sun.COM  *
3007917SReza.Sabdar@Sun.COM  * Returns:
3017917SReza.Sabdar@Sun.COM  *   void
3027917SReza.Sabdar@Sun.COM  */
3037917SReza.Sabdar@Sun.COM /*ARGSUSED*/
3047917SReza.Sabdar@Sun.COM void
3057917SReza.Sabdar@Sun.COM ndmpd_data_abort_v2(ndmp_connection_t *connection, void *body)
3067917SReza.Sabdar@Sun.COM {
3077917SReza.Sabdar@Sun.COM 	ndmp_data_abort_reply reply;
3087917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
3097917SReza.Sabdar@Sun.COM 
3107917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state == NDMP_DATA_STATE_IDLE ||
3117917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_state == NDMP_DATA_STATE_HALTED) {
3127917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid state to process abort request.");
3137917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
3147917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
3157917SReza.Sabdar@Sun.COM 		    "sending data_abort reply");
3167917SReza.Sabdar@Sun.COM 		return;
3177917SReza.Sabdar@Sun.COM 	}
3187917SReza.Sabdar@Sun.COM 	/*
3197917SReza.Sabdar@Sun.COM 	 * Don't go to HALTED state yet. Need to wait for data operation to
3207917SReza.Sabdar@Sun.COM 	 * abort. When this happens, ndmpd_done will get called and will
3217917SReza.Sabdar@Sun.COM 	 * perform the halt processing.
3227917SReza.Sabdar@Sun.COM 	 */
3237917SReza.Sabdar@Sun.COM 	session->ns_data.dd_abort = TRUE;
3247917SReza.Sabdar@Sun.COM 	(*session->ns_data.dd_module.dm_abort_func)(
3257917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_module.dm_module_cookie);
3267917SReza.Sabdar@Sun.COM 
3277917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
3287917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply, "sending data_abort reply");
3297917SReza.Sabdar@Sun.COM }
3307917SReza.Sabdar@Sun.COM 
3317917SReza.Sabdar@Sun.COM /*
3327917SReza.Sabdar@Sun.COM  * ************************************************************************
3337917SReza.Sabdar@Sun.COM  * NDMP V3 HANDLERS
3347917SReza.Sabdar@Sun.COM  * ************************************************************************
3357917SReza.Sabdar@Sun.COM  */
3367917SReza.Sabdar@Sun.COM 
3377917SReza.Sabdar@Sun.COM /*
3387917SReza.Sabdar@Sun.COM  * ndmpd_data_get_state_v3
3397917SReza.Sabdar@Sun.COM  *
3407917SReza.Sabdar@Sun.COM  * Request handler. Returns current data state.
3417917SReza.Sabdar@Sun.COM  *
3427917SReza.Sabdar@Sun.COM  * Parameters:
3437917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
3447917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
3457917SReza.Sabdar@Sun.COM  *
3467917SReza.Sabdar@Sun.COM  * Returns:
3477917SReza.Sabdar@Sun.COM  *   void
3487917SReza.Sabdar@Sun.COM  */
3497917SReza.Sabdar@Sun.COM /*ARGSUSED*/
3507917SReza.Sabdar@Sun.COM void
3517917SReza.Sabdar@Sun.COM ndmpd_data_get_state_v3(ndmp_connection_t *connection, void *body)
3527917SReza.Sabdar@Sun.COM {
3537917SReza.Sabdar@Sun.COM 	ndmp_data_get_state_reply_v3 reply;
3547917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
3557917SReza.Sabdar@Sun.COM 
3567917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
3577917SReza.Sabdar@Sun.COM 
3587917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
3597917SReza.Sabdar@Sun.COM 	reply.invalid = NDMP_DATA_STATE_EST_BYTES_REMAIN_INVALID
3607917SReza.Sabdar@Sun.COM 	    | NDMP_DATA_STATE_EST_TIME_REMAIN_INVALID;
3617917SReza.Sabdar@Sun.COM 	reply.operation = session->ns_data.dd_operation;
3627917SReza.Sabdar@Sun.COM 	reply.state = session->ns_data.dd_state;
3637917SReza.Sabdar@Sun.COM 	reply.halt_reason = session->ns_data.dd_halt_reason;
3647917SReza.Sabdar@Sun.COM 
3657917SReza.Sabdar@Sun.COM 	if (reply.operation == NDMP_DATA_OP_BACKUP)
3667917SReza.Sabdar@Sun.COM 		reply.bytes_processed =
3677917SReza.Sabdar@Sun.COM 		    long_long_to_quad(
3687917SReza.Sabdar@Sun.COM 		    session->ns_data.dd_module.dm_stats.ms_bytes_processed);
3697917SReza.Sabdar@Sun.COM 	else
3707917SReza.Sabdar@Sun.COM 		reply.bytes_processed =
3717917SReza.Sabdar@Sun.COM 		    long_long_to_quad(ndmpd_data_get_info(session));
3727917SReza.Sabdar@Sun.COM 
3737917SReza.Sabdar@Sun.COM 	reply.est_bytes_remain = long_long_to_quad(0LL);
3747917SReza.Sabdar@Sun.COM 	reply.est_time_remain = 0;
3757917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE)
3767917SReza.Sabdar@Sun.COM 		ndmp_copy_addr_v3(&reply.data_connection_addr,
3777917SReza.Sabdar@Sun.COM 		    &session->ns_data.dd_data_addr);
3787917SReza.Sabdar@Sun.COM 	reply.read_offset = long_long_to_quad(session->ns_data.dd_read_offset);
3797917SReza.Sabdar@Sun.COM 	reply.read_length = long_long_to_quad(session->ns_data.dd_read_length);
3807917SReza.Sabdar@Sun.COM 
3817917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
3827917SReza.Sabdar@Sun.COM 	    "sending ndmp_data_get_state_v3 reply");
3837917SReza.Sabdar@Sun.COM }
3847917SReza.Sabdar@Sun.COM 
3857917SReza.Sabdar@Sun.COM 
3867917SReza.Sabdar@Sun.COM /*
3877917SReza.Sabdar@Sun.COM  * ndmpd_data_start_backup_v3
3887917SReza.Sabdar@Sun.COM  *
3897917SReza.Sabdar@Sun.COM  * Request handler. Starts a backup.
3907917SReza.Sabdar@Sun.COM  *
3917917SReza.Sabdar@Sun.COM  * Parameters:
3927917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
3937917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
3947917SReza.Sabdar@Sun.COM  *
3957917SReza.Sabdar@Sun.COM  * Returns:
3967917SReza.Sabdar@Sun.COM  *   void
3977917SReza.Sabdar@Sun.COM  */
3987917SReza.Sabdar@Sun.COM void
3997917SReza.Sabdar@Sun.COM ndmpd_data_start_backup_v3(ndmp_connection_t *connection, void *body)
4007917SReza.Sabdar@Sun.COM {
4017917SReza.Sabdar@Sun.COM 	ndmp_data_start_backup_request_v3 *request;
4027917SReza.Sabdar@Sun.COM 	ndmp_data_start_backup_reply_v3 reply;
4037917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
4047917SReza.Sabdar@Sun.COM 	ndmp_error err;
4057917SReza.Sabdar@Sun.COM 
4067917SReza.Sabdar@Sun.COM 	request = (ndmp_data_start_backup_request_v3 *)body;
4077917SReza.Sabdar@Sun.COM 
4087917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
4097917SReza.Sabdar@Sun.COM 
4107917SReza.Sabdar@Sun.COM 	err = start_backup_v3(session, request->bu_type, request->env.env_val,
4117917SReza.Sabdar@Sun.COM 	    request->env.env_len);
4127917SReza.Sabdar@Sun.COM 
4137917SReza.Sabdar@Sun.COM 	/*
4147917SReza.Sabdar@Sun.COM 	 * start_backup_v3 sends the reply if the backup is
4157917SReza.Sabdar@Sun.COM 	 * successfully started.  Otherwise, send the reply
4167917SReza.Sabdar@Sun.COM 	 * containing the error here.
4177917SReza.Sabdar@Sun.COM 	 */
4187917SReza.Sabdar@Sun.COM 	if (err != NDMP_NO_ERR) {
4197917SReza.Sabdar@Sun.COM 		reply.error = err;
4207917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
4217917SReza.Sabdar@Sun.COM 		    "sending data_start_backup_v3 reply");
4227917SReza.Sabdar@Sun.COM 		ndmpd_data_cleanup(session);
4237917SReza.Sabdar@Sun.COM 	}
4247917SReza.Sabdar@Sun.COM }
4257917SReza.Sabdar@Sun.COM 
4267917SReza.Sabdar@Sun.COM 
4277917SReza.Sabdar@Sun.COM /*
4287917SReza.Sabdar@Sun.COM  * ndmpd_data_start_recover_v3
4297917SReza.Sabdar@Sun.COM  *
4307917SReza.Sabdar@Sun.COM  * Request handler. Starts a restore.
4317917SReza.Sabdar@Sun.COM  *
4327917SReza.Sabdar@Sun.COM  * Parameters:
4337917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
4347917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
4357917SReza.Sabdar@Sun.COM  *
4367917SReza.Sabdar@Sun.COM  * Returns:
4377917SReza.Sabdar@Sun.COM  *   void
4387917SReza.Sabdar@Sun.COM  */
4397917SReza.Sabdar@Sun.COM void
4407917SReza.Sabdar@Sun.COM ndmpd_data_start_recover_v3(ndmp_connection_t *connection, void *body)
4417917SReza.Sabdar@Sun.COM {
4427917SReza.Sabdar@Sun.COM 	ndmp_data_start_recover_request_v3 *request;
4437917SReza.Sabdar@Sun.COM 	ndmp_data_start_recover_reply_v3 reply;
4447917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
4457917SReza.Sabdar@Sun.COM 	ndmp_error err;
4467917SReza.Sabdar@Sun.COM 
4477917SReza.Sabdar@Sun.COM 	request = (ndmp_data_start_recover_request_v3 *)body;
4487917SReza.Sabdar@Sun.COM 
4497917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
4507917SReza.Sabdar@Sun.COM 
4517917SReza.Sabdar@Sun.COM 	err = start_recover_v3(session, request->bu_type, request->env.env_val,
4527917SReza.Sabdar@Sun.COM 	    request->env.env_len, request->nlist.nlist_val,
4537917SReza.Sabdar@Sun.COM 	    request->nlist.nlist_len);
4547917SReza.Sabdar@Sun.COM 
4557917SReza.Sabdar@Sun.COM 	/*
4567917SReza.Sabdar@Sun.COM 	 * start_recover_v3 sends the reply if the recover is
4577917SReza.Sabdar@Sun.COM 	 * successfully started.  Otherwise, send the reply
4587917SReza.Sabdar@Sun.COM 	 * containing the error here.
4597917SReza.Sabdar@Sun.COM 	 */
4607917SReza.Sabdar@Sun.COM 	if (err != NDMP_NO_ERR) {
4617917SReza.Sabdar@Sun.COM 		reply.error = err;
4627917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
4637917SReza.Sabdar@Sun.COM 		    "sending data_start_recover_v3 reply");
4647917SReza.Sabdar@Sun.COM 		ndmpd_data_error(session, NDMP_DATA_HALT_INTERNAL_ERROR);
4657917SReza.Sabdar@Sun.COM 		ndmpd_data_cleanup(session);
4667917SReza.Sabdar@Sun.COM 	}
4677917SReza.Sabdar@Sun.COM }
4687917SReza.Sabdar@Sun.COM 
4697917SReza.Sabdar@Sun.COM 
4707917SReza.Sabdar@Sun.COM /*
4717917SReza.Sabdar@Sun.COM  * ndmpd_data_abort_v3
4727917SReza.Sabdar@Sun.COM  *
4737917SReza.Sabdar@Sun.COM  * Request handler. Aborts the current backup/restore. The operation
4747917SReza.Sabdar@Sun.COM  * state is not changed to the halted state until after the operation
4757917SReza.Sabdar@Sun.COM  * has actually been aborted and the notify_halt request has been sent.
4767917SReza.Sabdar@Sun.COM  *
4777917SReza.Sabdar@Sun.COM  * Parameters:
4787917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
4797917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
4807917SReza.Sabdar@Sun.COM  *
4817917SReza.Sabdar@Sun.COM  * Returns:
4827917SReza.Sabdar@Sun.COM  *   void
4837917SReza.Sabdar@Sun.COM  */
4847917SReza.Sabdar@Sun.COM /*ARGSUSED*/
4857917SReza.Sabdar@Sun.COM void
4867917SReza.Sabdar@Sun.COM ndmpd_data_abort_v3(ndmp_connection_t *connection, void *body)
4877917SReza.Sabdar@Sun.COM {
4887917SReza.Sabdar@Sun.COM 	ndmp_data_abort_reply reply;
4897917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
4907917SReza.Sabdar@Sun.COM 
4917917SReza.Sabdar@Sun.COM 	switch (session->ns_data.dd_state) {
4927917SReza.Sabdar@Sun.COM 	case NDMP_DATA_STATE_IDLE:
4937917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
4947917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid state to process abort request.");
4957917SReza.Sabdar@Sun.COM 		break;
4967917SReza.Sabdar@Sun.COM 
4977917SReza.Sabdar@Sun.COM 	case NDMP_DATA_STATE_ACTIVE:
4987917SReza.Sabdar@Sun.COM 		/*
4997917SReza.Sabdar@Sun.COM 		 * Don't go to HALTED state yet.  Need to wait for data
5007917SReza.Sabdar@Sun.COM 		 * operation to abort.  When this happens, ndmpd_done_v3
5017917SReza.Sabdar@Sun.COM 		 * will get called and will perform the halt processing.
5027917SReza.Sabdar@Sun.COM 		 */
5037917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
5047917SReza.Sabdar@Sun.COM 		session->ns_data.dd_abort = TRUE;
5057917SReza.Sabdar@Sun.COM 		if (session->ns_data.dd_module.dm_abort_func)
5067917SReza.Sabdar@Sun.COM 			(*session->ns_data.dd_module.dm_abort_func)(
5077917SReza.Sabdar@Sun.COM 			    session->ns_data.dd_module.dm_module_cookie);
5087917SReza.Sabdar@Sun.COM 		break;
5097917SReza.Sabdar@Sun.COM 
5107917SReza.Sabdar@Sun.COM 	case NDMP_DATA_STATE_HALTED:
5117917SReza.Sabdar@Sun.COM 	case NDMP_DATA_STATE_LISTEN:
5127917SReza.Sabdar@Sun.COM 	case NDMP_DATA_STATE_CONNECTED:
5137917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
5147917SReza.Sabdar@Sun.COM 		session->ns_data.dd_abort = TRUE;
5157917SReza.Sabdar@Sun.COM 		ndmpd_data_error(session, NDMP_DATA_HALT_ABORTED);
5167917SReza.Sabdar@Sun.COM 		break;
5177917SReza.Sabdar@Sun.COM 	default:
5187917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
5197917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Unknown data V3 state %d",
5207917SReza.Sabdar@Sun.COM 		    session->ns_data.dd_state);
5217917SReza.Sabdar@Sun.COM 	}
5227917SReza.Sabdar@Sun.COM 
5237917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
5247917SReza.Sabdar@Sun.COM 	    "sending data_abort_v3 reply");
5257917SReza.Sabdar@Sun.COM }
5267917SReza.Sabdar@Sun.COM 
5277917SReza.Sabdar@Sun.COM 
5287917SReza.Sabdar@Sun.COM /*
5297917SReza.Sabdar@Sun.COM  * ndmpd_data_stop_v3
5307917SReza.Sabdar@Sun.COM  *
5317917SReza.Sabdar@Sun.COM  * Request handler. Stops the current data operation.
5327917SReza.Sabdar@Sun.COM  *
5337917SReza.Sabdar@Sun.COM  * Parameters:
5347917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
5357917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
5367917SReza.Sabdar@Sun.COM  *
5377917SReza.Sabdar@Sun.COM  * Returns:
5387917SReza.Sabdar@Sun.COM  *   void
5397917SReza.Sabdar@Sun.COM  */
5407917SReza.Sabdar@Sun.COM /*ARGSUSED*/
5417917SReza.Sabdar@Sun.COM void
5427917SReza.Sabdar@Sun.COM ndmpd_data_stop_v3(ndmp_connection_t *connection, void *body)
5437917SReza.Sabdar@Sun.COM {
5447917SReza.Sabdar@Sun.COM 	ndmp_data_stop_reply reply;
5457917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
5467917SReza.Sabdar@Sun.COM 
5477917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_HALTED) {
5487917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid state to process stop request.");
5497917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
5507917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
5517917SReza.Sabdar@Sun.COM 		    "sending data_stop_v3 reply");
5527917SReza.Sabdar@Sun.COM 		return;
5537917SReza.Sabdar@Sun.COM 	}
5547917SReza.Sabdar@Sun.COM 	ndmp_waitfor_op(session);
5557917SReza.Sabdar@Sun.COM 	ndmpd_data_cleanup(session);
5567917SReza.Sabdar@Sun.COM 	ndmpd_file_history_cleanup(session, FALSE);
5577917SReza.Sabdar@Sun.COM 
5587917SReza.Sabdar@Sun.COM 	/* prepare for another data operation */
5597917SReza.Sabdar@Sun.COM 	(void) ndmpd_data_init(session);
5607917SReza.Sabdar@Sun.COM 	ndmpd_file_history_init(session);
5617917SReza.Sabdar@Sun.COM 
5627917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
5637917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
5647917SReza.Sabdar@Sun.COM 	    "sending data_stop_v3 reply");
5657917SReza.Sabdar@Sun.COM }
5667917SReza.Sabdar@Sun.COM 
5677917SReza.Sabdar@Sun.COM 
5687917SReza.Sabdar@Sun.COM /*
5697917SReza.Sabdar@Sun.COM  * ndmpd_data_listen_v3
5707917SReza.Sabdar@Sun.COM  *
5717917SReza.Sabdar@Sun.COM  * Request handler. Configures the server to listen for a connection
5727917SReza.Sabdar@Sun.COM  * from a remote mover.
5737917SReza.Sabdar@Sun.COM  *
5747917SReza.Sabdar@Sun.COM  * Parameters:
5757917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
5767917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
5777917SReza.Sabdar@Sun.COM  *
5787917SReza.Sabdar@Sun.COM  * Returns:
5797917SReza.Sabdar@Sun.COM  *   void
5807917SReza.Sabdar@Sun.COM  */
5817917SReza.Sabdar@Sun.COM void
5827917SReza.Sabdar@Sun.COM ndmpd_data_listen_v3(ndmp_connection_t *connection, void *body)
5837917SReza.Sabdar@Sun.COM {
5847917SReza.Sabdar@Sun.COM 	ndmp_data_listen_request_v3 *request;
5857917SReza.Sabdar@Sun.COM 	ndmp_data_listen_reply_v3 reply;
5867917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
5877917SReza.Sabdar@Sun.COM 	ulong_t addr;
5887917SReza.Sabdar@Sun.COM 	ushort_t port;
5897917SReza.Sabdar@Sun.COM 
5907917SReza.Sabdar@Sun.COM 	request = (ndmp_data_listen_request_v3 *)body;
5917917SReza.Sabdar@Sun.COM 
5927917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
5937917SReza.Sabdar@Sun.COM 
5947917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
5957917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
5967917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR,
5977917SReza.Sabdar@Sun.COM 		    "Invalid internal data state to process listen request.");
5987917SReza.Sabdar@Sun.COM 	} else if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) {
5997917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
6007917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR,
6017917SReza.Sabdar@Sun.COM 		    "Invalid mover state to process listen request.");
6027917SReza.Sabdar@Sun.COM 	} else {
6037917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
6047917SReza.Sabdar@Sun.COM 	}
6057917SReza.Sabdar@Sun.COM 
6067917SReza.Sabdar@Sun.COM 	if (reply.error != NDMP_NO_ERR) {
6077917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
6087917SReza.Sabdar@Sun.COM 		    "ndmp_data_listen_request_v3 reply");
6097917SReza.Sabdar@Sun.COM 		return;
6107917SReza.Sabdar@Sun.COM 	}
6117917SReza.Sabdar@Sun.COM 
6127917SReza.Sabdar@Sun.COM 	switch (request->addr_type) {
6137917SReza.Sabdar@Sun.COM 	case NDMP_ADDR_LOCAL:
6147917SReza.Sabdar@Sun.COM 		reply.data_connection_addr.addr_type = request->addr_type;
6157917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_LOCAL;
6167917SReza.Sabdar@Sun.COM 		break;
6177917SReza.Sabdar@Sun.COM 	case NDMP_ADDR_TCP:
6187917SReza.Sabdar@Sun.COM 		if (create_listen_socket_v3(session, &addr, &port) < 0) {
6197917SReza.Sabdar@Sun.COM 			reply.error = NDMP_IO_ERR;
6207917SReza.Sabdar@Sun.COM 			break;
6217917SReza.Sabdar@Sun.COM 		}
6227917SReza.Sabdar@Sun.COM 
6237917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
6247917SReza.Sabdar@Sun.COM 		reply.data_connection_addr.addr_type = request->addr_type;
6257917SReza.Sabdar@Sun.COM 		reply.data_connection_addr.tcp_ip_v3 = htonl(addr);
6267917SReza.Sabdar@Sun.COM 		reply.data_connection_addr.tcp_port_v3 = htons(port);
6277917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_TCP;
6287917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr.tcp_ip_v3 = addr;
6297917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr.tcp_port_v3 = ntohs(port);
6307917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "listen_socket: %d",
6317917SReza.Sabdar@Sun.COM 		    session->ns_data.dd_listen_sock);
6327917SReza.Sabdar@Sun.COM 		break;
6337917SReza.Sabdar@Sun.COM 
6347917SReza.Sabdar@Sun.COM 	default:
6357917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Invalid address type: %d",
6367917SReza.Sabdar@Sun.COM 		    request->addr_type);
6377917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
6387917SReza.Sabdar@Sun.COM 		break;
6397917SReza.Sabdar@Sun.COM 	}
6407917SReza.Sabdar@Sun.COM 
6417917SReza.Sabdar@Sun.COM 	if (reply.error == NDMP_NO_ERR)
6427917SReza.Sabdar@Sun.COM 		session->ns_data.dd_state = NDMP_DATA_STATE_LISTEN;
6437917SReza.Sabdar@Sun.COM 
6447917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
6457917SReza.Sabdar@Sun.COM 	    "ndmp_data_listen_request_v3 reply");
6467917SReza.Sabdar@Sun.COM }
6477917SReza.Sabdar@Sun.COM 
6487917SReza.Sabdar@Sun.COM 
6497917SReza.Sabdar@Sun.COM /*
6507917SReza.Sabdar@Sun.COM  * ndmpd_data_connect_v3
6517917SReza.Sabdar@Sun.COM  *
6527917SReza.Sabdar@Sun.COM  * Request handler. Connects the data server to either a local
6537917SReza.Sabdar@Sun.COM  * or remote mover.
6547917SReza.Sabdar@Sun.COM  *
6557917SReza.Sabdar@Sun.COM  * Parameters:
6567917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
6577917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
6587917SReza.Sabdar@Sun.COM  *
6597917SReza.Sabdar@Sun.COM  * Returns:
6607917SReza.Sabdar@Sun.COM  *   void
6617917SReza.Sabdar@Sun.COM  */
6627917SReza.Sabdar@Sun.COM void
6637917SReza.Sabdar@Sun.COM ndmpd_data_connect_v3(ndmp_connection_t *connection, void *body)
6647917SReza.Sabdar@Sun.COM {
6657917SReza.Sabdar@Sun.COM 	ndmp_data_connect_request_v3 *request;
6667917SReza.Sabdar@Sun.COM 	ndmp_data_connect_reply_v3 reply;
6677917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
6687917SReza.Sabdar@Sun.COM 
6697917SReza.Sabdar@Sun.COM 	request = (ndmp_data_connect_request_v3 *)body;
6707917SReza.Sabdar@Sun.COM 
6717917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
6727917SReza.Sabdar@Sun.COM 
6737917SReza.Sabdar@Sun.COM 	if (!ndmp_valid_v3addr_type(request->addr.addr_type)) {
6747917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
6757917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Invalid address type %d",
6767917SReza.Sabdar@Sun.COM 		    request->addr.addr_type);
6777917SReza.Sabdar@Sun.COM 	} else if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
6787917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
6797917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid state to process connect request.");
6807917SReza.Sabdar@Sun.COM 	} else {
6817917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
6827917SReza.Sabdar@Sun.COM 	}
6837917SReza.Sabdar@Sun.COM 
6847917SReza.Sabdar@Sun.COM 	if (reply.error != NDMP_NO_ERR) {
6857917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
6867917SReza.Sabdar@Sun.COM 		    "sending ndmp_data_connect_v3 reply");
6877917SReza.Sabdar@Sun.COM 		return;
6887917SReza.Sabdar@Sun.COM 	}
6897917SReza.Sabdar@Sun.COM 
6907917SReza.Sabdar@Sun.COM 	switch (request->addr.addr_type) {
6917917SReza.Sabdar@Sun.COM 	case NDMP_ADDR_LOCAL:
6927917SReza.Sabdar@Sun.COM 		/*
6937917SReza.Sabdar@Sun.COM 		 * Verify that the mover is listening for a
6947917SReza.Sabdar@Sun.COM 		 * local connection
6957917SReza.Sabdar@Sun.COM 		 */
6967917SReza.Sabdar@Sun.COM 		if (session->ns_mover.md_state != NDMP_MOVER_STATE_LISTEN ||
6977917SReza.Sabdar@Sun.COM 		    session->ns_mover.md_listen_sock != -1) {
6987917SReza.Sabdar@Sun.COM 			reply.error = NDMP_ILLEGAL_STATE_ERR;
6997917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_ERR,
7007917SReza.Sabdar@Sun.COM 			    "Mover is not in local listen state.");
7017917SReza.Sabdar@Sun.COM 		} else {
7027917SReza.Sabdar@Sun.COM 			session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE;
7037917SReza.Sabdar@Sun.COM 		}
7047917SReza.Sabdar@Sun.COM 		break;
7057917SReza.Sabdar@Sun.COM 
7067917SReza.Sabdar@Sun.COM 	case NDMP_ADDR_TCP:
7077917SReza.Sabdar@Sun.COM 		reply.error = data_connect_sock_v3(session,
7087917SReza.Sabdar@Sun.COM 		    request->addr.tcp_ip_v3, request->addr.tcp_port_v3);
7097917SReza.Sabdar@Sun.COM 		break;
7107917SReza.Sabdar@Sun.COM 
7117917SReza.Sabdar@Sun.COM 	default:
7127917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
7137917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Invalid address type %d",
7147917SReza.Sabdar@Sun.COM 		    request->addr.addr_type);
7157917SReza.Sabdar@Sun.COM 	}
7167917SReza.Sabdar@Sun.COM 
7177917SReza.Sabdar@Sun.COM 	if (reply.error == NDMP_NO_ERR)
7187917SReza.Sabdar@Sun.COM 		session->ns_data.dd_state = NDMP_DATA_STATE_CONNECTED;
7197917SReza.Sabdar@Sun.COM 
7207917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
7217917SReza.Sabdar@Sun.COM 	    "sending ndmp_data_connect_v3 reply");
7227917SReza.Sabdar@Sun.COM }
7237917SReza.Sabdar@Sun.COM 
7247917SReza.Sabdar@Sun.COM 
7257917SReza.Sabdar@Sun.COM /*
7267917SReza.Sabdar@Sun.COM  * ************************************************************************
7277917SReza.Sabdar@Sun.COM  * NDMP V4 HANDLERS
7287917SReza.Sabdar@Sun.COM  * ************************************************************************
7297917SReza.Sabdar@Sun.COM  */
7307917SReza.Sabdar@Sun.COM 
7317917SReza.Sabdar@Sun.COM /*
7327917SReza.Sabdar@Sun.COM  * ndmpd_data_get_env_v4
7337917SReza.Sabdar@Sun.COM  *
7347917SReza.Sabdar@Sun.COM  * Request handler. Returns the environment variable array sent
7357917SReza.Sabdar@Sun.COM  * with the backup request. This request may only be sent with
7367917SReza.Sabdar@Sun.COM  * a backup operation is in progress.
7377917SReza.Sabdar@Sun.COM  *
7387917SReza.Sabdar@Sun.COM  * Parameters:
7397917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
7407917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
7417917SReza.Sabdar@Sun.COM  *
7427917SReza.Sabdar@Sun.COM  * Returns:
7437917SReza.Sabdar@Sun.COM  *   void
7447917SReza.Sabdar@Sun.COM  */
7457917SReza.Sabdar@Sun.COM /*ARGSUSED*/
7467917SReza.Sabdar@Sun.COM void
7477917SReza.Sabdar@Sun.COM ndmpd_data_get_env_v4(ndmp_connection_t *connection, void *body)
7487917SReza.Sabdar@Sun.COM {
7497917SReza.Sabdar@Sun.COM 	ndmp_data_get_env_reply reply;
7507917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
7517917SReza.Sabdar@Sun.COM 
7527917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
7537917SReza.Sabdar@Sun.COM 
7547917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_ACTIVE &&
7557917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_state != NDMP_DATA_STATE_HALTED) {
7567917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid state for the data server.");
7577917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
7587917SReza.Sabdar@Sun.COM 		reply.env.env_len = 0;
7597917SReza.Sabdar@Sun.COM 	} else if (session->ns_data.dd_operation != NDMP_DATA_OP_BACKUP) {
7607917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Backup operation not active.");
7617917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
7627917SReza.Sabdar@Sun.COM 		reply.env.env_len = 0;
7637917SReza.Sabdar@Sun.COM 	} else {
7647917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
7657917SReza.Sabdar@Sun.COM 		reply.env.env_len = session->ns_data.dd_env_len;
7667917SReza.Sabdar@Sun.COM 		reply.env.env_val = session->ns_data.dd_env;
7677917SReza.Sabdar@Sun.COM 	}
7687917SReza.Sabdar@Sun.COM 
7697917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply, "sending data_get_env reply");
7707917SReza.Sabdar@Sun.COM }
7717917SReza.Sabdar@Sun.COM 
7727917SReza.Sabdar@Sun.COM /*
7737917SReza.Sabdar@Sun.COM  * ndmpd_data_get_state_v4
7747917SReza.Sabdar@Sun.COM  *
7757917SReza.Sabdar@Sun.COM  * Request handler. Returns current data state.
7767917SReza.Sabdar@Sun.COM  *
7777917SReza.Sabdar@Sun.COM  * Parameters:
7787917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
7797917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
7807917SReza.Sabdar@Sun.COM  *
7817917SReza.Sabdar@Sun.COM  * Returns:
7827917SReza.Sabdar@Sun.COM  *   void
7837917SReza.Sabdar@Sun.COM  */
7847917SReza.Sabdar@Sun.COM /*ARGSUSED*/
7857917SReza.Sabdar@Sun.COM void
7867917SReza.Sabdar@Sun.COM ndmpd_data_get_state_v4(ndmp_connection_t *connection, void *body)
7877917SReza.Sabdar@Sun.COM {
7887917SReza.Sabdar@Sun.COM 	ndmp_data_get_state_reply_v4 reply;
7897917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
7907917SReza.Sabdar@Sun.COM 
7917917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
7927917SReza.Sabdar@Sun.COM 
7937917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
7947917SReza.Sabdar@Sun.COM 	reply.unsupported = NDMP_DATA_STATE_EST_BYTES_REMAIN_INVALID
7957917SReza.Sabdar@Sun.COM 	    | NDMP_DATA_STATE_EST_TIME_REMAIN_INVALID;
7967917SReza.Sabdar@Sun.COM 	reply.operation = session->ns_data.dd_operation;
7977917SReza.Sabdar@Sun.COM 	reply.state = session->ns_data.dd_state;
7987917SReza.Sabdar@Sun.COM 	reply.halt_reason = session->ns_data.dd_halt_reason;
7997917SReza.Sabdar@Sun.COM 
8007917SReza.Sabdar@Sun.COM 	if (reply.operation == NDMP_DATA_OP_BACKUP)
8017917SReza.Sabdar@Sun.COM 		reply.bytes_processed = long_long_to_quad(
8027917SReza.Sabdar@Sun.COM 		    session->ns_data.dd_module.dm_stats.ms_bytes_processed);
8037917SReza.Sabdar@Sun.COM 	else
8047917SReza.Sabdar@Sun.COM 		reply.bytes_processed =
8057917SReza.Sabdar@Sun.COM 		    long_long_to_quad(ndmpd_data_get_info(session));
8067917SReza.Sabdar@Sun.COM 
8077917SReza.Sabdar@Sun.COM 	reply.est_bytes_remain = long_long_to_quad(0LL);
8087917SReza.Sabdar@Sun.COM 	reply.est_time_remain = 0;
8097917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE)
8107917SReza.Sabdar@Sun.COM 		ndmp_copy_addr_v4(&reply.data_connection_addr,
8117917SReza.Sabdar@Sun.COM 		    &session->ns_data.dd_data_addr_v4);
8127917SReza.Sabdar@Sun.COM 
8137917SReza.Sabdar@Sun.COM 	reply.read_offset = long_long_to_quad(session->ns_data.dd_read_offset);
8147917SReza.Sabdar@Sun.COM 	reply.read_length = long_long_to_quad(session->ns_data.dd_read_length);
8157917SReza.Sabdar@Sun.COM 
8167917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
8177917SReza.Sabdar@Sun.COM 	    "sending ndmp_data_get_state_v4 reply");
8187917SReza.Sabdar@Sun.COM 	free(reply.data_connection_addr.tcp_addr_v4);
8197917SReza.Sabdar@Sun.COM }
8207917SReza.Sabdar@Sun.COM 
8217917SReza.Sabdar@Sun.COM 
8227917SReza.Sabdar@Sun.COM /*
8237917SReza.Sabdar@Sun.COM  * ndmpd_data_connect_v4
8247917SReza.Sabdar@Sun.COM  *
8257917SReza.Sabdar@Sun.COM  * Request handler. Connects the data server to either a local
8267917SReza.Sabdar@Sun.COM  * or remote mover.
8277917SReza.Sabdar@Sun.COM  *
8287917SReza.Sabdar@Sun.COM  * Parameters:
8297917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
8307917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
8317917SReza.Sabdar@Sun.COM  *
8327917SReza.Sabdar@Sun.COM  * Returns:
8337917SReza.Sabdar@Sun.COM  *   void
8347917SReza.Sabdar@Sun.COM  */
8357917SReza.Sabdar@Sun.COM void
8367917SReza.Sabdar@Sun.COM ndmpd_data_connect_v4(ndmp_connection_t *connection, void *body)
8377917SReza.Sabdar@Sun.COM {
8387917SReza.Sabdar@Sun.COM 	ndmp_data_connect_request_v4 *request;
8397917SReza.Sabdar@Sun.COM 	ndmp_data_connect_reply_v4 reply;
8407917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
8417917SReza.Sabdar@Sun.COM 
8427917SReza.Sabdar@Sun.COM 	request = (ndmp_data_connect_request_v4 *)body;
8437917SReza.Sabdar@Sun.COM 
8447917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
8457917SReza.Sabdar@Sun.COM 
8467917SReza.Sabdar@Sun.COM 	if (!ndmp_valid_v3addr_type(request->addr.addr_type)) {
8477917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
8487917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Invalid address type %d",
8497917SReza.Sabdar@Sun.COM 		    request->addr.addr_type);
8507917SReza.Sabdar@Sun.COM 	} else if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
8517917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
8527917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid state to process connect request.");
8537917SReza.Sabdar@Sun.COM 	} else {
8547917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
8557917SReza.Sabdar@Sun.COM 	}
8567917SReza.Sabdar@Sun.COM 
8577917SReza.Sabdar@Sun.COM 	if (reply.error != NDMP_NO_ERR) {
8587917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
8597917SReza.Sabdar@Sun.COM 		    "sending ndmp_data_connect_v4 reply");
8607917SReza.Sabdar@Sun.COM 		return;
8617917SReza.Sabdar@Sun.COM 	}
8627917SReza.Sabdar@Sun.COM 
8637917SReza.Sabdar@Sun.COM 	switch (request->addr.addr_type) {
8647917SReza.Sabdar@Sun.COM 	case NDMP_ADDR_LOCAL:
8657917SReza.Sabdar@Sun.COM 		/*
8667917SReza.Sabdar@Sun.COM 		 * Verify that the mover is listening for a
8677917SReza.Sabdar@Sun.COM 		 * local connection
8687917SReza.Sabdar@Sun.COM 		 */
8697917SReza.Sabdar@Sun.COM 		if (session->ns_mover.md_state != NDMP_MOVER_STATE_LISTEN ||
8707917SReza.Sabdar@Sun.COM 		    session->ns_mover.md_listen_sock != -1) {
8717917SReza.Sabdar@Sun.COM 			reply.error = NDMP_ILLEGAL_STATE_ERR;
8727917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_ERR,
8737917SReza.Sabdar@Sun.COM 			    "Mover is not in local listen state.");
8747917SReza.Sabdar@Sun.COM 		} else {
8757917SReza.Sabdar@Sun.COM 			session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE;
8767917SReza.Sabdar@Sun.COM 		}
8777917SReza.Sabdar@Sun.COM 		break;
8787917SReza.Sabdar@Sun.COM 
8797917SReza.Sabdar@Sun.COM 	case NDMP_ADDR_TCP:
8807917SReza.Sabdar@Sun.COM 		reply.error = data_connect_sock_v3(session,
8817917SReza.Sabdar@Sun.COM 		    request->addr.tcp_ip_v4(0), request->addr.tcp_port_v4(0));
8827917SReza.Sabdar@Sun.COM 		break;
8837917SReza.Sabdar@Sun.COM 
8847917SReza.Sabdar@Sun.COM 	default:
8857917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
8867917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Invalid address type %d",
8877917SReza.Sabdar@Sun.COM 		    request->addr.addr_type);
8887917SReza.Sabdar@Sun.COM 	}
8897917SReza.Sabdar@Sun.COM 
8907917SReza.Sabdar@Sun.COM 	if (reply.error == NDMP_NO_ERR)
8917917SReza.Sabdar@Sun.COM 		session->ns_data.dd_state = NDMP_DATA_STATE_CONNECTED;
8927917SReza.Sabdar@Sun.COM 
8937917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
8947917SReza.Sabdar@Sun.COM 	    "sending ndmp_data_connect_v4 reply");
8957917SReza.Sabdar@Sun.COM }
8967917SReza.Sabdar@Sun.COM 
8977917SReza.Sabdar@Sun.COM /*
8987917SReza.Sabdar@Sun.COM  * ndmpd_data_listen_v4
8997917SReza.Sabdar@Sun.COM  *
9007917SReza.Sabdar@Sun.COM  * Request handler. Configures the server to listen for a connection
9017917SReza.Sabdar@Sun.COM  * from a remote mover.
9027917SReza.Sabdar@Sun.COM  *
9037917SReza.Sabdar@Sun.COM  * Parameters:
9047917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
9057917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
9067917SReza.Sabdar@Sun.COM  *
9077917SReza.Sabdar@Sun.COM  * Returns:
9087917SReza.Sabdar@Sun.COM  *   void
9097917SReza.Sabdar@Sun.COM  */
9107917SReza.Sabdar@Sun.COM void
9117917SReza.Sabdar@Sun.COM ndmpd_data_listen_v4(ndmp_connection_t *connection, void *body)
9127917SReza.Sabdar@Sun.COM {
9137917SReza.Sabdar@Sun.COM 	ndmp_data_listen_request_v4 *request;
9147917SReza.Sabdar@Sun.COM 	ndmp_data_listen_reply_v4 reply;
9157917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
9167917SReza.Sabdar@Sun.COM 	ulong_t addr;
9177917SReza.Sabdar@Sun.COM 	ushort_t port;
9187917SReza.Sabdar@Sun.COM 
9197917SReza.Sabdar@Sun.COM 	request = (ndmp_data_listen_request_v4 *)body;
9207917SReza.Sabdar@Sun.COM 
9217917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
9227917SReza.Sabdar@Sun.COM 
9237917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
9247917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
9257917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR,
9267917SReza.Sabdar@Sun.COM 		    "Invalid internal data state to process listen request.");
9277917SReza.Sabdar@Sun.COM 	} else if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) {
9287917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
9297917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR,
9307917SReza.Sabdar@Sun.COM 		    "Invalid mover state to process listen request.");
9317917SReza.Sabdar@Sun.COM 	} else {
9327917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
9337917SReza.Sabdar@Sun.COM 	}
9347917SReza.Sabdar@Sun.COM 
9357917SReza.Sabdar@Sun.COM 	if (reply.error != NDMP_NO_ERR) {
9367917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
9377917SReza.Sabdar@Sun.COM 		    "ndmp_data_listen_request_v4 reply");
9387917SReza.Sabdar@Sun.COM 		return;
9397917SReza.Sabdar@Sun.COM 	}
9407917SReza.Sabdar@Sun.COM 
9417917SReza.Sabdar@Sun.COM 	switch (request->addr_type) {
9427917SReza.Sabdar@Sun.COM 	case NDMP_ADDR_LOCAL:
9437917SReza.Sabdar@Sun.COM 		reply.connect_addr.addr_type = request->addr_type;
9447917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_LOCAL;
9457917SReza.Sabdar@Sun.COM 		break;
9467917SReza.Sabdar@Sun.COM 	case NDMP_ADDR_TCP:
9477917SReza.Sabdar@Sun.COM 		if (create_listen_socket_v3(session, &addr, &port) < 0) {
9487917SReza.Sabdar@Sun.COM 			reply.error = NDMP_IO_ERR;
9497917SReza.Sabdar@Sun.COM 			break;
9507917SReza.Sabdar@Sun.COM 		}
9517917SReza.Sabdar@Sun.COM 
9527917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
9537917SReza.Sabdar@Sun.COM 		reply.connect_addr.addr_type = request->addr_type;
9547917SReza.Sabdar@Sun.COM 		reply.connect_addr.tcp_addr_v4 =
9557917SReza.Sabdar@Sun.COM 		    ndmp_malloc(sizeof (ndmp_tcp_addr_v4));
9567917SReza.Sabdar@Sun.COM 
9577917SReza.Sabdar@Sun.COM 		reply.connect_addr.tcp_ip_v4(0) = htonl(addr);
9587917SReza.Sabdar@Sun.COM 		reply.connect_addr.tcp_port_v4(0) = htons(port);
9597917SReza.Sabdar@Sun.COM 		reply.connect_addr.tcp_len_v4 = 1;
9607917SReza.Sabdar@Sun.COM 
9617917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr_v4.addr_type = NDMP_ADDR_TCP;
9627917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr_v4.tcp_addr_v4 =
9637917SReza.Sabdar@Sun.COM 		    ndmp_malloc(sizeof (ndmp_tcp_addr_v4));
9647917SReza.Sabdar@Sun.COM 
9657917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr_v4.tcp_ip_v4(0) = addr;
9667917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr_v4.tcp_port_v4(0) = ntohs(port);
9677917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr_v4.tcp_len_v4 = 1;
9687917SReza.Sabdar@Sun.COM 
9697917SReza.Sabdar@Sun.COM 		/* Copy that to data_addr for compatibility */
9707917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_TCP;
9717917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr.tcp_ip_v3 = addr;
9727917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr.tcp_port_v3 = ntohs(port);
9737917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "listen_socket: %d",
9747917SReza.Sabdar@Sun.COM 		    session->ns_data.dd_listen_sock);
9757917SReza.Sabdar@Sun.COM 		break;
9767917SReza.Sabdar@Sun.COM 
9777917SReza.Sabdar@Sun.COM 	default:
9787917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Invalid address type: %d",
9797917SReza.Sabdar@Sun.COM 		    request->addr_type);
9807917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
9817917SReza.Sabdar@Sun.COM 		break;
9827917SReza.Sabdar@Sun.COM 	}
9837917SReza.Sabdar@Sun.COM 
9847917SReza.Sabdar@Sun.COM 	if (reply.error == NDMP_NO_ERR)
9857917SReza.Sabdar@Sun.COM 		session->ns_data.dd_state = NDMP_DATA_STATE_LISTEN;
9867917SReza.Sabdar@Sun.COM 
9877917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
9887917SReza.Sabdar@Sun.COM 	    "ndmp_data_listen_request_v4 reply");
9897917SReza.Sabdar@Sun.COM }
9907917SReza.Sabdar@Sun.COM 
9917917SReza.Sabdar@Sun.COM 
9927917SReza.Sabdar@Sun.COM /*
9937917SReza.Sabdar@Sun.COM  * ndmpd_data_start_recover_filehist_v4
9947917SReza.Sabdar@Sun.COM  *
9957917SReza.Sabdar@Sun.COM  * Request handler. Recovers the file history (not supported yet)
9967917SReza.Sabdar@Sun.COM  * This command has an optional support in V4.
9977917SReza.Sabdar@Sun.COM  *
9987917SReza.Sabdar@Sun.COM  * Parameters:
9997917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
10007917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
10017917SReza.Sabdar@Sun.COM  *
10027917SReza.Sabdar@Sun.COM  * Returns:
10037917SReza.Sabdar@Sun.COM  *   void
10047917SReza.Sabdar@Sun.COM  */
10057917SReza.Sabdar@Sun.COM /*ARGSUSED*/
10067917SReza.Sabdar@Sun.COM void
10077917SReza.Sabdar@Sun.COM ndmpd_data_start_recover_filehist_v4(ndmp_connection_t *connection, void *body)
10087917SReza.Sabdar@Sun.COM {
10097917SReza.Sabdar@Sun.COM 	ndmp_data_start_recover_filehist_reply_v4 reply;
10107917SReza.Sabdar@Sun.COM 
10117917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "Request not supported");
10127917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NOT_SUPPORTED_ERR;
10137917SReza.Sabdar@Sun.COM 
10147917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
10157917SReza.Sabdar@Sun.COM 	    "sending ndmp_data_start_recover_filehist_reply_v4 reply");
10167917SReza.Sabdar@Sun.COM }
10177917SReza.Sabdar@Sun.COM 
10187917SReza.Sabdar@Sun.COM /*
10197917SReza.Sabdar@Sun.COM  * ************************************************************************
10207917SReza.Sabdar@Sun.COM  * LOCALS
10217917SReza.Sabdar@Sun.COM  * ************************************************************************
10227917SReza.Sabdar@Sun.COM  */
10237917SReza.Sabdar@Sun.COM 
10247917SReza.Sabdar@Sun.COM /*
10257917SReza.Sabdar@Sun.COM  * ndmpd_data_error_send
10267917SReza.Sabdar@Sun.COM  *
10277917SReza.Sabdar@Sun.COM  * This function sends the notify message to the client.
10287917SReza.Sabdar@Sun.COM  *
10297917SReza.Sabdar@Sun.COM  * Parameters:
10307917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
10317917SReza.Sabdar@Sun.COM  *   reason  (input) - halt reason.
10327917SReza.Sabdar@Sun.COM  *
10337917SReza.Sabdar@Sun.COM  * Returns:
10347917SReza.Sabdar@Sun.COM  *   Error code
10357917SReza.Sabdar@Sun.COM  */
10367917SReza.Sabdar@Sun.COM /*ARGSUSED*/
10377917SReza.Sabdar@Sun.COM static int
10387917SReza.Sabdar@Sun.COM ndmpd_data_error_send(ndmpd_session_t *session, ndmp_data_halt_reason reason)
10397917SReza.Sabdar@Sun.COM {
10407917SReza.Sabdar@Sun.COM 	ndmp_notify_data_halted_request req;
10417917SReza.Sabdar@Sun.COM 
10427917SReza.Sabdar@Sun.COM 	req.reason = session->ns_data.dd_halt_reason;
10437917SReza.Sabdar@Sun.COM 	req.text_reason = "";
10447917SReza.Sabdar@Sun.COM 
10457917SReza.Sabdar@Sun.COM 	return (ndmp_send_request(session->ns_connection,
10467917SReza.Sabdar@Sun.COM 	    NDMP_NOTIFY_DATA_HALTED, NDMP_NO_ERR, &req, 0));
10477917SReza.Sabdar@Sun.COM }
10487917SReza.Sabdar@Sun.COM 
10497917SReza.Sabdar@Sun.COM 
10507917SReza.Sabdar@Sun.COM /*
10517917SReza.Sabdar@Sun.COM  * ndmpd_data_error_send_v4
10527917SReza.Sabdar@Sun.COM  *
10537917SReza.Sabdar@Sun.COM  * This function sends the notify message to the client.
10547917SReza.Sabdar@Sun.COM  *
10557917SReza.Sabdar@Sun.COM  * Parameters:
10567917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
10577917SReza.Sabdar@Sun.COM  *   reason  (input) - halt reason.
10587917SReza.Sabdar@Sun.COM  *
10597917SReza.Sabdar@Sun.COM  * Returns:
10607917SReza.Sabdar@Sun.COM  *   Error code
10617917SReza.Sabdar@Sun.COM  */
10627917SReza.Sabdar@Sun.COM /*ARGSUSED*/
10637917SReza.Sabdar@Sun.COM static int
10647917SReza.Sabdar@Sun.COM ndmpd_data_error_send_v4(ndmpd_session_t *session, ndmp_data_halt_reason reason)
10657917SReza.Sabdar@Sun.COM {
10667917SReza.Sabdar@Sun.COM 	ndmp_notify_data_halted_request_v4 req;
10677917SReza.Sabdar@Sun.COM 
10687917SReza.Sabdar@Sun.COM 	req.reason = session->ns_data.dd_halt_reason;
10697917SReza.Sabdar@Sun.COM 
10707917SReza.Sabdar@Sun.COM 	return ndmp_send_request(session->ns_connection,
10717917SReza.Sabdar@Sun.COM 	    NDMP_NOTIFY_DATA_HALTED, NDMP_NO_ERR, &req, 0);
10727917SReza.Sabdar@Sun.COM }
10737917SReza.Sabdar@Sun.COM 
10747917SReza.Sabdar@Sun.COM 
10757917SReza.Sabdar@Sun.COM /*
10767917SReza.Sabdar@Sun.COM  * ndmpd_data_error
10777917SReza.Sabdar@Sun.COM  *
10787917SReza.Sabdar@Sun.COM  * This function is called when a data error has been detected.
10797917SReza.Sabdar@Sun.COM  * A notify message is sent to the client and the data server is
10807917SReza.Sabdar@Sun.COM  * placed into the halted state.
10817917SReza.Sabdar@Sun.COM  *
10827917SReza.Sabdar@Sun.COM  * Parameters:
10837917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
10847917SReza.Sabdar@Sun.COM  *   reason  (input) - halt reason.
10857917SReza.Sabdar@Sun.COM  *
10867917SReza.Sabdar@Sun.COM  * Returns:
10877917SReza.Sabdar@Sun.COM  *   void
10887917SReza.Sabdar@Sun.COM  */
10897917SReza.Sabdar@Sun.COM void
10907917SReza.Sabdar@Sun.COM ndmpd_data_error(ndmpd_session_t *session, ndmp_data_halt_reason reason)
10917917SReza.Sabdar@Sun.COM {
10927917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state == NDMP_DATA_STATE_IDLE ||
10937917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_state == NDMP_DATA_STATE_HALTED)
10947917SReza.Sabdar@Sun.COM 		return;
10957917SReza.Sabdar@Sun.COM 
10967917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_operation == NDMP_DATA_OP_BACKUP) {
10977917SReza.Sabdar@Sun.COM 		/*
10987917SReza.Sabdar@Sun.COM 		 * Send/discard any buffered file history data.
10997917SReza.Sabdar@Sun.COM 		 */
11007917SReza.Sabdar@Sun.COM 		ndmpd_file_history_cleanup(session,
11017917SReza.Sabdar@Sun.COM 		    (reason == NDMP_DATA_HALT_SUCCESSFUL ? TRUE : FALSE));
11027917SReza.Sabdar@Sun.COM 
11037917SReza.Sabdar@Sun.COM 		/*
11047917SReza.Sabdar@Sun.COM 		 * If mover local and successful backup, write any
11057917SReza.Sabdar@Sun.COM 		 * remaining buffered data to tape.
11067917SReza.Sabdar@Sun.COM 		 */
11077917SReza.Sabdar@Sun.COM 		if (session->ns_data.dd_data_addr.addr_type
11087917SReza.Sabdar@Sun.COM 		    == NDMP_ADDR_LOCAL && reason == NDMP_DATA_HALT_SUCCESSFUL)
11097917SReza.Sabdar@Sun.COM 			(void) ndmpd_local_write_v3(session, 0, 0);
11107917SReza.Sabdar@Sun.COM 	}
11117917SReza.Sabdar@Sun.COM 
11127917SReza.Sabdar@Sun.COM 	session->ns_data.dd_state = NDMP_DATA_STATE_HALTED;
11137917SReza.Sabdar@Sun.COM 	session->ns_data.dd_halt_reason = reason;
11147917SReza.Sabdar@Sun.COM 
11157917SReza.Sabdar@Sun.COM 	if (session->ns_protocol_version == NDMPV4) {
11167917SReza.Sabdar@Sun.COM 		if (ndmpd_data_error_send_v4(session, reason) < 0)
11177917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG,
11187917SReza.Sabdar@Sun.COM 			    "Error sending notify_data_halted request");
11197917SReza.Sabdar@Sun.COM 	} else {
11207917SReza.Sabdar@Sun.COM 		if (ndmpd_data_error_send(session, reason) < 0)
11217917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG,
11227917SReza.Sabdar@Sun.COM 			    "Error sending notify_data_halted request");
11237917SReza.Sabdar@Sun.COM 	}
11247917SReza.Sabdar@Sun.COM 
11257917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_TCP) {
11267917SReza.Sabdar@Sun.COM 		if (session->ns_data.dd_sock != -1) {
11277917SReza.Sabdar@Sun.COM 			(void) ndmpd_remove_file_handler(session,
11287917SReza.Sabdar@Sun.COM 			    session->ns_data.dd_sock);
11297917SReza.Sabdar@Sun.COM 			/*
11307917SReza.Sabdar@Sun.COM 			 * ndmpcopy: we use the same socket for the mover,
11317917SReza.Sabdar@Sun.COM 			 * so expect to close when mover is done!
11327917SReza.Sabdar@Sun.COM 			 */
11337917SReza.Sabdar@Sun.COM 			if (session->ns_data.dd_sock !=
11347917SReza.Sabdar@Sun.COM 			    session->ns_mover.md_sock)
11357917SReza.Sabdar@Sun.COM 				(void) close(session->ns_data.dd_sock);
11367917SReza.Sabdar@Sun.COM 
11377917SReza.Sabdar@Sun.COM 			session->ns_data.dd_sock = -1;
11387917SReza.Sabdar@Sun.COM 		}
11397917SReza.Sabdar@Sun.COM 		if (session->ns_data.dd_listen_sock != -1) {
11407917SReza.Sabdar@Sun.COM 			(void) ndmpd_remove_file_handler(session,
11417917SReza.Sabdar@Sun.COM 			    session->ns_data.dd_listen_sock);
11427917SReza.Sabdar@Sun.COM 
11437917SReza.Sabdar@Sun.COM 			(void) close(session->ns_data.dd_listen_sock);
11447917SReza.Sabdar@Sun.COM 			session->ns_data.dd_listen_sock = -1;
11457917SReza.Sabdar@Sun.COM 		}
11467917SReza.Sabdar@Sun.COM 	} else {
11477917SReza.Sabdar@Sun.COM 		ndmpd_mover_error(session, NDMP_MOVER_HALT_CONNECT_CLOSED);
11487917SReza.Sabdar@Sun.COM 	}
11497917SReza.Sabdar@Sun.COM }
11507917SReza.Sabdar@Sun.COM 
11517917SReza.Sabdar@Sun.COM 
11527917SReza.Sabdar@Sun.COM /*
11537917SReza.Sabdar@Sun.COM  * data_accept_connection_v3
11547917SReza.Sabdar@Sun.COM  *
11557917SReza.Sabdar@Sun.COM  * Accept a data connection from a remote mover.
11567917SReza.Sabdar@Sun.COM  * Called by ndmpd_select when a connection is pending on
11577917SReza.Sabdar@Sun.COM  * the data listen socket.
11587917SReza.Sabdar@Sun.COM  *
11597917SReza.Sabdar@Sun.COM  * Parameters:
11607917SReza.Sabdar@Sun.COM  *   cookie  (input) - session pointer.
11617917SReza.Sabdar@Sun.COM  *   fd      (input) - file descriptor.
11627917SReza.Sabdar@Sun.COM  *   mode    (input) - select mode.
11637917SReza.Sabdar@Sun.COM  *
11647917SReza.Sabdar@Sun.COM  * Returns:
11657917SReza.Sabdar@Sun.COM  *   void
11667917SReza.Sabdar@Sun.COM  */
11677917SReza.Sabdar@Sun.COM /*ARGSUSED*/
11687917SReza.Sabdar@Sun.COM static void
11697917SReza.Sabdar@Sun.COM data_accept_connection_v3(void *cookie, int fd, ulong_t mode)
11707917SReza.Sabdar@Sun.COM {
11717917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = (ndmpd_session_t *)cookie;
11727917SReza.Sabdar@Sun.COM 	int from_len;
11737917SReza.Sabdar@Sun.COM 	struct sockaddr_in from;
11747917SReza.Sabdar@Sun.COM 	int flag = 1;
11757917SReza.Sabdar@Sun.COM 
11767917SReza.Sabdar@Sun.COM 	from_len = sizeof (from);
11777917SReza.Sabdar@Sun.COM 	session->ns_data.dd_sock = accept(fd, (struct sockaddr *)&from,
11787917SReza.Sabdar@Sun.COM 	    &from_len);
11797917SReza.Sabdar@Sun.COM 
11807917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "sock fd: %d",
11817917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_sock);
11827917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "sin: port %d addr %s",
11837917SReza.Sabdar@Sun.COM 	    ntohs(from.sin_port),
11847917SReza.Sabdar@Sun.COM 	    inet_ntoa(IN_ADDR(from.sin_addr.s_addr)));
11857917SReza.Sabdar@Sun.COM 
11867917SReza.Sabdar@Sun.COM 	(void) ndmpd_remove_file_handler(session, fd);
11877917SReza.Sabdar@Sun.COM 	(void) close(session->ns_data.dd_listen_sock);
11887917SReza.Sabdar@Sun.COM 	session->ns_data.dd_listen_sock = -1;
11897917SReza.Sabdar@Sun.COM 
11907917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_sock < 0) {
11917917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Accept error: %m");
11927917SReza.Sabdar@Sun.COM 		ndmpd_data_error(session, NDMP_DATA_HALT_CONNECT_ERROR);
11937917SReza.Sabdar@Sun.COM 		return;
11947917SReza.Sabdar@Sun.COM 	}
11957917SReza.Sabdar@Sun.COM 
11967917SReza.Sabdar@Sun.COM 	/*
11977917SReza.Sabdar@Sun.COM 	 * Save the peer address.
11987917SReza.Sabdar@Sun.COM 	 */
11997917SReza.Sabdar@Sun.COM 	session->ns_data.dd_data_addr.tcp_ip_v3 = from.sin_addr.s_addr;
12007917SReza.Sabdar@Sun.COM 	session->ns_data.dd_data_addr.tcp_port_v3 = ntohs(from.sin_port);
12017917SReza.Sabdar@Sun.COM 
12027917SReza.Sabdar@Sun.COM 	/*
12037917SReza.Sabdar@Sun.COM 	 * Set the parameter of the new socket.
12047917SReza.Sabdar@Sun.COM 	 */
12057917SReza.Sabdar@Sun.COM 	(void) setsockopt(session->ns_data.dd_sock, SOL_SOCKET, SO_KEEPALIVE,
12067917SReza.Sabdar@Sun.COM 	    &flag, sizeof (flag));
12077917SReza.Sabdar@Sun.COM 	ndmp_set_socket_nodelay(session->ns_data.dd_sock);
12087917SReza.Sabdar@Sun.COM 	if (ndmp_sbs > 0)
12097917SReza.Sabdar@Sun.COM 		ndmp_set_socket_snd_buf(session->ns_data.dd_sock,
12107917SReza.Sabdar@Sun.COM 		    ndmp_sbs * KILOBYTE);
12117917SReza.Sabdar@Sun.COM 	if (ndmp_rbs > 0)
12127917SReza.Sabdar@Sun.COM 		ndmp_set_socket_rcv_buf(session->ns_data.dd_sock,
12137917SReza.Sabdar@Sun.COM 		    ndmp_rbs * KILOBYTE);
12147917SReza.Sabdar@Sun.COM 
12157917SReza.Sabdar@Sun.COM 	session->ns_data.dd_state = NDMP_DATA_STATE_CONNECTED;
12167917SReza.Sabdar@Sun.COM }
12177917SReza.Sabdar@Sun.COM 
12187917SReza.Sabdar@Sun.COM 
12197917SReza.Sabdar@Sun.COM /*
12207917SReza.Sabdar@Sun.COM  * create_listen_socket_v3
12217917SReza.Sabdar@Sun.COM  *
12227917SReza.Sabdar@Sun.COM  * Creates the data sockets for listening for a remote mover/data
12237917SReza.Sabdar@Sun.COM  * incoming connections.
12247917SReza.Sabdar@Sun.COM  */
12257917SReza.Sabdar@Sun.COM static int
12267917SReza.Sabdar@Sun.COM create_listen_socket_v3(ndmpd_session_t *session, ulong_t *addr, ushort_t *port)
12277917SReza.Sabdar@Sun.COM {
12287917SReza.Sabdar@Sun.COM 	session->ns_data.dd_listen_sock = ndmp_create_socket(addr, port);
12297917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_listen_sock < 0)
12307917SReza.Sabdar@Sun.COM 		return (-1);
12317917SReza.Sabdar@Sun.COM 
12327917SReza.Sabdar@Sun.COM 	/*
12337917SReza.Sabdar@Sun.COM 	 * Add a file handler for the listen socket.
12347917SReza.Sabdar@Sun.COM 	 * ndmpd_select will call data_accept_connection when a
12357917SReza.Sabdar@Sun.COM 	 * connection is ready to be accepted.
12367917SReza.Sabdar@Sun.COM 	 */
12377917SReza.Sabdar@Sun.COM 	if (ndmpd_add_file_handler(session, (void*)session,
12387917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_listen_sock, NDMPD_SELECT_MODE_READ, HC_MOVER,
12397917SReza.Sabdar@Sun.COM 	    data_accept_connection_v3) < 0) {
12407917SReza.Sabdar@Sun.COM 		(void) close(session->ns_data.dd_listen_sock);
12417917SReza.Sabdar@Sun.COM 		session->ns_data.dd_listen_sock = -1;
12427917SReza.Sabdar@Sun.COM 		return (-1);
12437917SReza.Sabdar@Sun.COM 	}
12447917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "addr: %s:%d",
12457917SReza.Sabdar@Sun.COM 	    inet_ntoa(IN_ADDR(*addr)), ntohs(*port));
12467917SReza.Sabdar@Sun.COM 
12477917SReza.Sabdar@Sun.COM 	return (0);
12487917SReza.Sabdar@Sun.COM }
12497917SReza.Sabdar@Sun.COM 
12507917SReza.Sabdar@Sun.COM 
12517917SReza.Sabdar@Sun.COM /*
12527917SReza.Sabdar@Sun.COM  * data_connect_sock_v3
12537917SReza.Sabdar@Sun.COM  *
12547917SReza.Sabdar@Sun.COM  * Connect the data interface socket to the specified ip/port
12557917SReza.Sabdar@Sun.COM  *
12567917SReza.Sabdar@Sun.COM  * Parameters:
12577917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
12587917SReza.Sabdar@Sun.COM  *   addr    (input) - IP address
12597917SReza.Sabdar@Sun.COM  *   port    (input) - port number
12607917SReza.Sabdar@Sun.COM  *
12617917SReza.Sabdar@Sun.COM  * Returns:
12627917SReza.Sabdar@Sun.COM  *   NDMP_NO_ERR - backup successfully started.
12637917SReza.Sabdar@Sun.COM  *   otherwise - error code of backup start error.
12647917SReza.Sabdar@Sun.COM  */
12657917SReza.Sabdar@Sun.COM static ndmp_error
12667917SReza.Sabdar@Sun.COM data_connect_sock_v3(ndmpd_session_t *session, ulong_t addr, ushort_t port)
12677917SReza.Sabdar@Sun.COM {
12687917SReza.Sabdar@Sun.COM 	int sock;
12697917SReza.Sabdar@Sun.COM 
12707917SReza.Sabdar@Sun.COM 	sock = ndmp_connect_sock_v3(addr, port);
12717917SReza.Sabdar@Sun.COM 	if (sock < 0)
12727917SReza.Sabdar@Sun.COM 		return (NDMP_CONNECT_ERR);
12737917SReza.Sabdar@Sun.COM 
12747917SReza.Sabdar@Sun.COM 	session->ns_data.dd_sock = sock;
12757917SReza.Sabdar@Sun.COM 	session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_TCP;
12767917SReza.Sabdar@Sun.COM 	session->ns_data.dd_data_addr.tcp_ip_v3 = ntohl(addr);
12777917SReza.Sabdar@Sun.COM 	session->ns_data.dd_data_addr.tcp_port_v3 = port;
12787917SReza.Sabdar@Sun.COM 
12797917SReza.Sabdar@Sun.COM 	return (NDMP_NO_ERR);
12807917SReza.Sabdar@Sun.COM }
12817917SReza.Sabdar@Sun.COM 
12827917SReza.Sabdar@Sun.COM 
12837917SReza.Sabdar@Sun.COM /*
12847917SReza.Sabdar@Sun.COM  * start_backup_v3
12857917SReza.Sabdar@Sun.COM  *
12867917SReza.Sabdar@Sun.COM  * Start the backup work
12877917SReza.Sabdar@Sun.COM  *
12887917SReza.Sabdar@Sun.COM  * Parameters:
12897917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
12907917SReza.Sabdar@Sun.COM  *   bu_type (input) - backup type.
12917917SReza.Sabdar@Sun.COM  *   env_val (input) - environment variable array.
12927917SReza.Sabdar@Sun.COM  *   env_len (input) - length of env_val.
12937917SReza.Sabdar@Sun.COM  *
12947917SReza.Sabdar@Sun.COM  * Returns:
12957917SReza.Sabdar@Sun.COM  *   NDMP_NO_ERR - backup successfully started.
12967917SReza.Sabdar@Sun.COM  *   otherwise - error code of backup start error.
12977917SReza.Sabdar@Sun.COM  */
12987917SReza.Sabdar@Sun.COM static ndmp_error
12997917SReza.Sabdar@Sun.COM start_backup_v3(ndmpd_session_t *session, char *bu_type, ndmp_pval *env_val,
13007917SReza.Sabdar@Sun.COM     ulong_t env_len)
13017917SReza.Sabdar@Sun.COM {
13027917SReza.Sabdar@Sun.COM 	int err;
13037917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
13047917SReza.Sabdar@Sun.COM 	ndmpd_module_params_t *params;
13057917SReza.Sabdar@Sun.COM 	ndmp_data_start_backup_reply_v3 reply;
13067917SReza.Sabdar@Sun.COM 
13077917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
13087917SReza.Sabdar@Sun.COM 
13097917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_CONNECTED) {
13107917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR,
13117917SReza.Sabdar@Sun.COM 		    "Can't start new backup in current state.");
13127917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR,
13137917SReza.Sabdar@Sun.COM 		    "Connection to the mover is not established.");
13147917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_STATE_ERR);
13157917SReza.Sabdar@Sun.COM 	}
13167917SReza.Sabdar@Sun.COM 
13177917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_LOCAL) {
13187917SReza.Sabdar@Sun.COM 		if (session->ns_tape.td_mode == NDMP_TAPE_READ_MODE) {
13197917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_ERR, "Write protected device.");
13207917SReza.Sabdar@Sun.COM 			return (NDMP_WRITE_PROTECT_ERR);
13217917SReza.Sabdar@Sun.COM 		}
13227917SReza.Sabdar@Sun.COM 	}
13237917SReza.Sabdar@Sun.COM 
13247917SReza.Sabdar@Sun.COM 	if (strcmp(bu_type, NDMP_DUMP_TYPE) != 0 &&
13257917SReza.Sabdar@Sun.COM 	    strcmp(bu_type, NDMP_TAR_TYPE) != 0) {
13267917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid backup type: %s.", bu_type);
13277917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Supported backup types are tar and dump.");
13287917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
13297917SReza.Sabdar@Sun.COM 	}
13307917SReza.Sabdar@Sun.COM 
13317917SReza.Sabdar@Sun.COM 	err = ndmpd_save_env(session, env_val, env_len);
13327917SReza.Sabdar@Sun.COM 	if (err != NDMP_NO_ERR)
13337917SReza.Sabdar@Sun.COM 		return (err);
13347917SReza.Sabdar@Sun.COM 
13357917SReza.Sabdar@Sun.COM 	nlp = ndmp_get_nlp(session);
13367917SReza.Sabdar@Sun.COM 	NDMP_FREE(nlp->nlp_params);
13377917SReza.Sabdar@Sun.COM 	params = nlp->nlp_params = ndmp_malloc(sizeof (ndmpd_module_params_t));
13387917SReza.Sabdar@Sun.COM 	if (!params)
13397917SReza.Sabdar@Sun.COM 		return (NDMP_NO_MEM_ERR);
13407917SReza.Sabdar@Sun.COM 
13417917SReza.Sabdar@Sun.COM 	params->mp_daemon_cookie = (void *)session;
13427917SReza.Sabdar@Sun.COM 	params->mp_module_cookie = &session->ns_data.dd_module.dm_module_cookie;
13437917SReza.Sabdar@Sun.COM 	params->mp_protocol_version = session->ns_protocol_version;
13447917SReza.Sabdar@Sun.COM 	params->mp_operation = NDMP_DATA_OP_BACKUP;
13457917SReza.Sabdar@Sun.COM 	params->mp_get_env_func = ndmpd_api_get_env;
13467917SReza.Sabdar@Sun.COM 	params->mp_add_env_func = ndmpd_api_add_env;
13477917SReza.Sabdar@Sun.COM 	params->mp_set_env_func = ndmpd_api_set_env;
13487917SReza.Sabdar@Sun.COM 	params->mp_get_name_func = 0;
13497917SReza.Sabdar@Sun.COM 	params->mp_dispatch_func = ndmpd_api_dispatch;
13507917SReza.Sabdar@Sun.COM 	params->mp_done_func = ndmpd_api_done_v3;
13517917SReza.Sabdar@Sun.COM 	if (session->ns_protocol_version == NDMPV4)
13527917SReza.Sabdar@Sun.COM 		params->mp_log_func_v3 = ndmpd_api_log_v4;
13537917SReza.Sabdar@Sun.COM 	else
13547917SReza.Sabdar@Sun.COM 		params->mp_log_func_v3 = ndmpd_api_log_v3;
13557917SReza.Sabdar@Sun.COM 
13567917SReza.Sabdar@Sun.COM 	params->mp_add_file_handler_func = ndmpd_api_add_file_handler;
13577917SReza.Sabdar@Sun.COM 	params->mp_remove_file_handler_func = ndmpd_api_remove_file_handler;
13587917SReza.Sabdar@Sun.COM 	params->mp_write_func = ndmpd_api_write_v3;
13597917SReza.Sabdar@Sun.COM 	params->mp_read_func = 0;
13607917SReza.Sabdar@Sun.COM 	params->mp_file_recovered_func = 0;
13617917SReza.Sabdar@Sun.COM 	params->mp_stats = &session->ns_data.dd_module.dm_stats;
13627917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_module_cookie = 0;
13637917SReza.Sabdar@Sun.COM 
13647917SReza.Sabdar@Sun.COM 	if (strcmp(bu_type, NDMP_DUMP_TYPE) == 0) {
13657917SReza.Sabdar@Sun.COM 		NLP_SET(nlp, NLPF_DUMP);
13667917SReza.Sabdar@Sun.COM 		params->mp_file_history_path_func = 0;
13677917SReza.Sabdar@Sun.COM 		params->mp_file_history_dir_func =
13687917SReza.Sabdar@Sun.COM 		    ndmpd_api_file_history_dir_v3;
13697917SReza.Sabdar@Sun.COM 		params->mp_file_history_node_func =
13707917SReza.Sabdar@Sun.COM 		    ndmpd_api_file_history_node_v3;
13717917SReza.Sabdar@Sun.COM 	} else if (strcmp(bu_type, NDMP_TAR_TYPE) == 0) {
13727917SReza.Sabdar@Sun.COM 		NLP_SET(nlp, NLPF_TAR);
13737917SReza.Sabdar@Sun.COM 		params->mp_file_history_path_func =
13747917SReza.Sabdar@Sun.COM 		    ndmpd_api_file_history_file_v3;
13757917SReza.Sabdar@Sun.COM 		params->mp_file_history_dir_func = 0;
13767917SReza.Sabdar@Sun.COM 		params->mp_file_history_node_func = 0;
13777917SReza.Sabdar@Sun.COM 	} else {
13787917SReza.Sabdar@Sun.COM 		NLP_UNSET(nlp, NLPF_DUMP);
13797917SReza.Sabdar@Sun.COM 		NLP_UNSET(nlp, NLPF_TAR);
13807917SReza.Sabdar@Sun.COM 	}
13817917SReza.Sabdar@Sun.COM 
13827917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_start_func = ndmpd_tar_backup_starter_v3;
13837917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_abort_func = ndmpd_tar_backup_abort_v3;
13847917SReza.Sabdar@Sun.COM 
13857917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_bytes_remaining = 0;
13867917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_time_remaining  = 0;
13877917SReza.Sabdar@Sun.COM 	session->ns_data.dd_nlist_v3 = 0;
13887917SReza.Sabdar@Sun.COM 	session->ns_data.dd_nlist_len = 0;
13897917SReza.Sabdar@Sun.COM 	session->ns_data.dd_bytes_left_to_read = 0;
13907917SReza.Sabdar@Sun.COM 	session->ns_data.dd_position = 0;
13917917SReza.Sabdar@Sun.COM 	session->ns_data.dd_discard_length = 0;
13927917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_offset = 0;
13937917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_length = 0;
13947917SReza.Sabdar@Sun.COM 
13957917SReza.Sabdar@Sun.COM 	reply.error = ndmp_backup_get_params_v3(session, params);
13967917SReza.Sabdar@Sun.COM 	if (reply.error != NDMP_NO_ERR) {
13977917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "err: %d", err);
13987917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
13997917SReza.Sabdar@Sun.COM 		return (reply.error);
14007917SReza.Sabdar@Sun.COM 	}
14017917SReza.Sabdar@Sun.COM 
14027917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
14037917SReza.Sabdar@Sun.COM 	if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
14047917SReza.Sabdar@Sun.COM 	    &reply) < 0) {
14057917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Sending data_start_backup_v3 reply");
14067917SReza.Sabdar@Sun.COM 		return (NDMP_NO_ERR);
14077917SReza.Sabdar@Sun.COM 	}
14087917SReza.Sabdar@Sun.COM 
14097917SReza.Sabdar@Sun.COM 	NS_INC(nbk);
14107917SReza.Sabdar@Sun.COM 	session->ns_data.dd_state = NDMP_DATA_STATE_ACTIVE;
14117917SReza.Sabdar@Sun.COM 	session->ns_data.dd_operation = NDMP_DATA_OP_BACKUP;
14127917SReza.Sabdar@Sun.COM 	session->ns_data.dd_abort = FALSE;
14137917SReza.Sabdar@Sun.COM 
14147917SReza.Sabdar@Sun.COM 	/*
14157917SReza.Sabdar@Sun.COM 	 * perform the backup
14167917SReza.Sabdar@Sun.COM 	 *
14177917SReza.Sabdar@Sun.COM 	 * Cannot wait for the thread to exit as we are replying the
14187917SReza.Sabdar@Sun.COM 	 * client request here.
14197917SReza.Sabdar@Sun.COM 	 */
14207917SReza.Sabdar@Sun.COM 	err = pthread_create(NULL, NULL,
14217917SReza.Sabdar@Sun.COM 	    (funct_t)session->ns_data.dd_module.dm_start_func,
14227917SReza.Sabdar@Sun.COM 	    params);
14237917SReza.Sabdar@Sun.COM 	if (err != 0) {
14247917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Can't start backup session.");
14257917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
14267917SReza.Sabdar@Sun.COM 	}
14277917SReza.Sabdar@Sun.COM 
14287917SReza.Sabdar@Sun.COM 	return (NDMP_NO_ERR);
14297917SReza.Sabdar@Sun.COM }
14307917SReza.Sabdar@Sun.COM 
14317917SReza.Sabdar@Sun.COM 
14327917SReza.Sabdar@Sun.COM /*
14337917SReza.Sabdar@Sun.COM  * start_recover_v3
14347917SReza.Sabdar@Sun.COM  *
14357917SReza.Sabdar@Sun.COM  * Start the restore work
14367917SReza.Sabdar@Sun.COM  *
14377917SReza.Sabdar@Sun.COM  * Parameters:
14387917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
14397917SReza.Sabdar@Sun.COM  *   bu_type   (input) - backup type.
14407917SReza.Sabdar@Sun.COM  *   env_val   (input) - environment variable array.
14417917SReza.Sabdar@Sun.COM  *   env_len   (input) - length of env_val.
14427917SReza.Sabdar@Sun.COM  *
14437917SReza.Sabdar@Sun.COM  * Returns:
14447917SReza.Sabdar@Sun.COM  *   NDMP_NO_ERR - recover successfully started.
14457917SReza.Sabdar@Sun.COM  *   otherwise   - error code of recover start error.
14467917SReza.Sabdar@Sun.COM  */
14477917SReza.Sabdar@Sun.COM static ndmp_error
14487917SReza.Sabdar@Sun.COM start_recover_v3(ndmpd_session_t *session, char *bu_type, ndmp_pval *env_val,
14497917SReza.Sabdar@Sun.COM     ulong_t env_len, ndmp_name_v3 *nlist_val, ulong_t nlist_len)
14507917SReza.Sabdar@Sun.COM {
14517917SReza.Sabdar@Sun.COM 	ndmp_data_start_recover_reply_v3 reply;
14527917SReza.Sabdar@Sun.COM 	ndmpd_module_params_t *params;
14537917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
14547917SReza.Sabdar@Sun.COM 	int err;
14557917SReza.Sabdar@Sun.COM 
14567917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
14577917SReza.Sabdar@Sun.COM 
14587917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_CONNECTED) {
14597917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Can't start new recover in current state.");
14607917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_STATE_ERR);
14617917SReza.Sabdar@Sun.COM 	}
14627917SReza.Sabdar@Sun.COM 	if (strcmp(bu_type, NDMP_DUMP_TYPE) != 0 &&
14637917SReza.Sabdar@Sun.COM 	    strcmp(bu_type, NDMP_TAR_TYPE) != 0) {
14647917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid backup type: %s.", bu_type);
14657917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Supported backup types are tar and dump.");
14667917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
14677917SReza.Sabdar@Sun.COM 	}
14687917SReza.Sabdar@Sun.COM 
14697917SReza.Sabdar@Sun.COM 	nlp = ndmp_get_nlp(session);
14707917SReza.Sabdar@Sun.COM 	NDMP_FREE(nlp->nlp_params);
14717917SReza.Sabdar@Sun.COM 	params = nlp->nlp_params = ndmp_malloc(sizeof (ndmpd_module_params_t));
14727917SReza.Sabdar@Sun.COM 	if (!params) {
14737917SReza.Sabdar@Sun.COM 		return (NDMP_NO_MEM_ERR);
14747917SReza.Sabdar@Sun.COM 	}
14757917SReza.Sabdar@Sun.COM 
14767917SReza.Sabdar@Sun.COM 	reply.error = ndmpd_save_env(session, env_val, env_len);
14777917SReza.Sabdar@Sun.COM 	if (reply.error != NDMP_NO_ERR) {
14787917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
14797917SReza.Sabdar@Sun.COM 		return (NDMP_NO_MEM_ERR);
14807917SReza.Sabdar@Sun.COM 	}
14817917SReza.Sabdar@Sun.COM 
14827917SReza.Sabdar@Sun.COM 	reply.error = ndmpd_save_nlist_v3(session, nlist_val, nlist_len);
14837917SReza.Sabdar@Sun.COM 	if (reply.error != NDMP_NO_ERR) {
14847917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
14857917SReza.Sabdar@Sun.COM 		return (NDMP_NO_MEM_ERR);
14867917SReza.Sabdar@Sun.COM 	}
14877917SReza.Sabdar@Sun.COM 
14887917SReza.Sabdar@Sun.COM 	/*
14897917SReza.Sabdar@Sun.COM 	 * Setup restore parameters.
14907917SReza.Sabdar@Sun.COM 	 */
14917917SReza.Sabdar@Sun.COM 	params->mp_daemon_cookie = (void *)session;
14927917SReza.Sabdar@Sun.COM 	params->mp_module_cookie = &session->ns_data.dd_module.dm_module_cookie;
14937917SReza.Sabdar@Sun.COM 	params->mp_protocol_version = session->ns_protocol_version;
14947917SReza.Sabdar@Sun.COM 	params->mp_operation = NDMP_DATA_OP_RECOVER;
14957917SReza.Sabdar@Sun.COM 	params->mp_get_env_func = ndmpd_api_get_env;
14967917SReza.Sabdar@Sun.COM 	params->mp_add_env_func = ndmpd_api_add_env;
14977917SReza.Sabdar@Sun.COM 	params->mp_set_env_func = ndmpd_api_set_env;
14987917SReza.Sabdar@Sun.COM 	params->mp_get_name_func = ndmpd_api_get_name_v3;
14997917SReza.Sabdar@Sun.COM 	params->mp_dispatch_func = ndmpd_api_dispatch;
15007917SReza.Sabdar@Sun.COM 	params->mp_done_func = ndmpd_api_done_v3;
15017917SReza.Sabdar@Sun.COM 	if (session->ns_protocol_version == NDMPV4) {
15027917SReza.Sabdar@Sun.COM 		params->mp_log_func_v3 = ndmpd_api_log_v4;
15037917SReza.Sabdar@Sun.COM 		params->mp_file_recovered_func = ndmpd_api_file_recovered_v4;
15047917SReza.Sabdar@Sun.COM 	} else {
15057917SReza.Sabdar@Sun.COM 		params->mp_log_func_v3 = ndmpd_api_log_v3;
15067917SReza.Sabdar@Sun.COM 		params->mp_file_recovered_func = ndmpd_api_file_recovered_v3;
15077917SReza.Sabdar@Sun.COM 	}
15087917SReza.Sabdar@Sun.COM 
15097917SReza.Sabdar@Sun.COM 	params->mp_add_file_handler_func = ndmpd_api_add_file_handler;
15107917SReza.Sabdar@Sun.COM 	params->mp_remove_file_handler_func = ndmpd_api_remove_file_handler;
15117917SReza.Sabdar@Sun.COM 	params->mp_write_func = 0;
15127917SReza.Sabdar@Sun.COM 	params->mp_file_history_path_func = 0;
15137917SReza.Sabdar@Sun.COM 	params->mp_file_history_dir_func = 0;
15147917SReza.Sabdar@Sun.COM 	params->mp_file_history_node_func = 0;
15157917SReza.Sabdar@Sun.COM 	params->mp_read_func = ndmpd_api_read_v3;
15167917SReza.Sabdar@Sun.COM 	params->mp_seek_func = ndmpd_api_seek_v3;
15177917SReza.Sabdar@Sun.COM 	params->mp_stats = &session->ns_data.dd_module.dm_stats;
15187917SReza.Sabdar@Sun.COM 
15197917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_module_cookie = 0;
15207917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_start_func = ndmpd_tar_restore_starter_v3;
15217917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_abort_func = ndmpd_tar_restore_abort_v3;
15227917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_bytes_remaining = 0;
15237917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_time_remaining = 0;
15247917SReza.Sabdar@Sun.COM 	session->ns_data.dd_bytes_left_to_read = 0;
15257917SReza.Sabdar@Sun.COM 	session->ns_data.dd_position = 0;
15267917SReza.Sabdar@Sun.COM 	session->ns_data.dd_discard_length = 0;
15277917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_offset = 0;
15287917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_length = 0;
15297917SReza.Sabdar@Sun.COM 
15307917SReza.Sabdar@Sun.COM 	err = ndmp_restore_get_params_v3(session, params);
15317917SReza.Sabdar@Sun.COM 	if (err != NDMP_NO_ERR) {
15327917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
15337917SReza.Sabdar@Sun.COM 		return (err);
15347917SReza.Sabdar@Sun.COM 	}
15357917SReza.Sabdar@Sun.COM 
15367917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
15377917SReza.Sabdar@Sun.COM 	if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
15387917SReza.Sabdar@Sun.COM 	    &reply) < 0) {
15397917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
15407917SReza.Sabdar@Sun.COM 		ndmpd_free_nlist_v3(session);
15417917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
15427917SReza.Sabdar@Sun.COM 		    "Error sending ndmp_data_start_recover_reply");
15437917SReza.Sabdar@Sun.COM 		ndmpd_data_error(session, NDMP_DATA_HALT_CONNECT_ERROR);
15447917SReza.Sabdar@Sun.COM 		return (NDMP_NO_ERR);
15457917SReza.Sabdar@Sun.COM 	}
15467917SReza.Sabdar@Sun.COM 
15477917SReza.Sabdar@Sun.COM 	NS_INC(nrs);
15487917SReza.Sabdar@Sun.COM 	session->ns_data.dd_state = NDMP_DATA_STATE_ACTIVE;
15497917SReza.Sabdar@Sun.COM 	session->ns_data.dd_operation = NDMP_DATA_OP_RECOVER;
15507917SReza.Sabdar@Sun.COM 	session->ns_data.dd_abort = FALSE;
15517917SReza.Sabdar@Sun.COM 
15527917SReza.Sabdar@Sun.COM 	/*
15537917SReza.Sabdar@Sun.COM 	 * perform the restore
15547917SReza.Sabdar@Sun.COM 	 *
15557917SReza.Sabdar@Sun.COM 	 * Cannot wait for the thread to exit as we are replying to the
15567917SReza.Sabdar@Sun.COM 	 * client request here.
15577917SReza.Sabdar@Sun.COM 	 */
15587917SReza.Sabdar@Sun.COM 	err = pthread_create(NULL, NULL,
15597917SReza.Sabdar@Sun.COM 	    (funct_t)session->ns_data.dd_module.dm_start_func,
15607917SReza.Sabdar@Sun.COM 	    params);
15617917SReza.Sabdar@Sun.COM 
15627917SReza.Sabdar@Sun.COM 	if (err != 0) {
15637917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Can't start recover session.");
15647917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
15657917SReza.Sabdar@Sun.COM 	}
15667917SReza.Sabdar@Sun.COM 	return (NDMP_NO_ERR);
15677917SReza.Sabdar@Sun.COM }
15687917SReza.Sabdar@Sun.COM 
15697917SReza.Sabdar@Sun.COM 
15707917SReza.Sabdar@Sun.COM /*
15717917SReza.Sabdar@Sun.COM  * discard_data_v3
15727917SReza.Sabdar@Sun.COM  *
15737917SReza.Sabdar@Sun.COM  * Read and discard data from the data connection.
15747917SReza.Sabdar@Sun.COM  * Called when a module has called ndmpd_seek() prior to
15757917SReza.Sabdar@Sun.COM  * reading all of the data from the previous seek.
15767917SReza.Sabdar@Sun.COM  *
15777917SReza.Sabdar@Sun.COM  * Parameters:
15787917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
15797917SReza.Sabdar@Sun.COM  *
15807917SReza.Sabdar@Sun.COM  * Returns:
15817917SReza.Sabdar@Sun.COM  *   number of bytes read and discarded.
15827917SReza.Sabdar@Sun.COM  *  -1 - error.
15837917SReza.Sabdar@Sun.COM  */
15847917SReza.Sabdar@Sun.COM static int
15857917SReza.Sabdar@Sun.COM discard_data_v3(ndmpd_session_t *session, ulong_t length)
15867917SReza.Sabdar@Sun.COM {
15877917SReza.Sabdar@Sun.COM 	static char buf[MAX_RECORD_SIZE];
15887917SReza.Sabdar@Sun.COM 	int n, toread;
15897917SReza.Sabdar@Sun.COM 
15907917SReza.Sabdar@Sun.COM 	toread = (length < MAX_RECORD_SIZE) ? length :
15917917SReza.Sabdar@Sun.COM 	    MAX_RECORD_SIZE;
15927917SReza.Sabdar@Sun.COM 
15937917SReza.Sabdar@Sun.COM 	/* Read and discard the data. */
15947917SReza.Sabdar@Sun.COM 	n = read(session->ns_data.dd_sock, buf, toread);
15957917SReza.Sabdar@Sun.COM 	if (n < 0) {
15967917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Socket read error: %m.");
15977917SReza.Sabdar@Sun.COM 		n = -1;
15987917SReza.Sabdar@Sun.COM 	}
15997917SReza.Sabdar@Sun.COM 
16007917SReza.Sabdar@Sun.COM 	return (n);
16017917SReza.Sabdar@Sun.COM }
16027917SReza.Sabdar@Sun.COM 
16037917SReza.Sabdar@Sun.COM 
16047917SReza.Sabdar@Sun.COM /*
16057917SReza.Sabdar@Sun.COM  * ndmpd_remote_read_v3
16067917SReza.Sabdar@Sun.COM  *
16077917SReza.Sabdar@Sun.COM  * Reads data from the remote mover.
16087917SReza.Sabdar@Sun.COM  *
16097917SReza.Sabdar@Sun.COM  * Parameters:
16107917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
16117917SReza.Sabdar@Sun.COM  *   data    (input) - data to be written.
16127917SReza.Sabdar@Sun.COM  *   length  (input) - data length.
16137917SReza.Sabdar@Sun.COM  *
16147917SReza.Sabdar@Sun.COM  * Returns:
16157917SReza.Sabdar@Sun.COM  *   0 - data successfully read.
16167917SReza.Sabdar@Sun.COM  *  -1 - error.
16177917SReza.Sabdar@Sun.COM  */
16187917SReza.Sabdar@Sun.COM int
16197917SReza.Sabdar@Sun.COM ndmpd_remote_read_v3(ndmpd_session_t *session, char *data, ulong_t length)
16207917SReza.Sabdar@Sun.COM {
16217917SReza.Sabdar@Sun.COM 	ulong_t count;
16227917SReza.Sabdar@Sun.COM 	ulong_t len;
16237917SReza.Sabdar@Sun.COM 	ssize_t n;
16247917SReza.Sabdar@Sun.COM 	ndmp_notify_data_read_request request;
16257917SReza.Sabdar@Sun.COM 	tlm_job_stats_t *jstat;
16267917SReza.Sabdar@Sun.COM 	longlong_t fsize;
16277917SReza.Sabdar@Sun.COM 
16287917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "ns_data.dd_xx: [%llu, %llu, %llu, %llu, %llu]",
16297917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_bytes_left_to_read,
16307917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_read_offset,
16317917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_read_length,
16327917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_position,
16337917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_discard_length);
16347917SReza.Sabdar@Sun.COM 
16357917SReza.Sabdar@Sun.COM 	count = 0;
16367917SReza.Sabdar@Sun.COM 	while (count < length) {
16377917SReza.Sabdar@Sun.COM 		len = length - count;
16387917SReza.Sabdar@Sun.COM 
16397917SReza.Sabdar@Sun.COM 		/*
16407917SReza.Sabdar@Sun.COM 		 * If the end of the seek window has been reached then
16417917SReza.Sabdar@Sun.COM 		 * send an ndmp_read request to the client.
16427917SReza.Sabdar@Sun.COM 		 * The NDMP client will then send a mover_data_read request to
16437917SReza.Sabdar@Sun.COM 		 * the remote mover and the mover will send more data.
16447917SReza.Sabdar@Sun.COM 		 * This condition can occur if the module attempts to read past
16457917SReza.Sabdar@Sun.COM 		 * a seek window set via a prior call to ndmpd_seek() or
16467917SReza.Sabdar@Sun.COM 		 * the module has not issued a seek. If no seek was issued then
16477917SReza.Sabdar@Sun.COM 		 * pretend that a seek was issued to read the entire tape.
16487917SReza.Sabdar@Sun.COM 		 */
16497917SReza.Sabdar@Sun.COM 		if (session->ns_data.dd_bytes_left_to_read == 0) {
16507917SReza.Sabdar@Sun.COM 			/* ndmpd_seek() never called? */
16517917SReza.Sabdar@Sun.COM 			if (session->ns_data.dd_read_length == 0) {
16527917SReza.Sabdar@Sun.COM 				session->ns_data.dd_bytes_left_to_read = ~0LL;
16537917SReza.Sabdar@Sun.COM 				session->ns_data.dd_read_offset = 0LL;
16547917SReza.Sabdar@Sun.COM 				session->ns_data.dd_read_length = ~0LL;
16557917SReza.Sabdar@Sun.COM 			} else {
16567917SReza.Sabdar@Sun.COM 				/*
16577917SReza.Sabdar@Sun.COM 				 * While restoring a file, restoreFile()
16587917SReza.Sabdar@Sun.COM 				 * records the number of bytes still need to
16597917SReza.Sabdar@Sun.COM 				 * be restored.  We use this as a guidance
16607917SReza.Sabdar@Sun.COM 				 * when asking for data from the tape.
16617917SReza.Sabdar@Sun.COM 				 */
16627917SReza.Sabdar@Sun.COM 				jstat = session->ns_ndmp_lbr_params->nlp_jstat;
16637917SReza.Sabdar@Sun.COM 				fsize = jstat->js_bytes_in_file;
16647917SReza.Sabdar@Sun.COM 
16657917SReza.Sabdar@Sun.COM 				NDMP_LOG(LOG_DEBUG, "bytes_left [%llu / %u]",
16667917SReza.Sabdar@Sun.COM 				    fsize, len);
16677917SReza.Sabdar@Sun.COM 
16687917SReza.Sabdar@Sun.COM 				/*
16697917SReza.Sabdar@Sun.COM 				 * Fall back to the old way if fsize if too
16707917SReza.Sabdar@Sun.COM 				 * small.
16717917SReza.Sabdar@Sun.COM 				 */
16727917SReza.Sabdar@Sun.COM 				if (fsize < len)
16737917SReza.Sabdar@Sun.COM 					fsize = len;
16747917SReza.Sabdar@Sun.COM 
16757917SReza.Sabdar@Sun.COM 				session->ns_data.dd_bytes_left_to_read = fsize;
16767917SReza.Sabdar@Sun.COM 				session->ns_data.dd_read_offset =
16777917SReza.Sabdar@Sun.COM 				    session->ns_data.dd_position;
16787917SReza.Sabdar@Sun.COM 				session->ns_data.dd_read_length = fsize;
16797917SReza.Sabdar@Sun.COM 			}
16807917SReza.Sabdar@Sun.COM 
16817917SReza.Sabdar@Sun.COM 			request.offset =
16827917SReza.Sabdar@Sun.COM 			    long_long_to_quad(session->ns_data.dd_read_offset);
16837917SReza.Sabdar@Sun.COM 			request.length =
16847917SReza.Sabdar@Sun.COM 			    long_long_to_quad(session->ns_data.dd_read_length);
16857917SReza.Sabdar@Sun.COM 
16867917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG, "to NOTIFY_DATA_READ [%llu, %llu]",
16877917SReza.Sabdar@Sun.COM 			    session->ns_data.dd_read_offset,
16887917SReza.Sabdar@Sun.COM 			    session->ns_data.dd_read_length);
16897917SReza.Sabdar@Sun.COM 
1690*8193SReza.Sabdar@Sun.COM 			if (ndmp_send_request_lock(session->ns_connection,
16917917SReza.Sabdar@Sun.COM 			    NDMP_NOTIFY_DATA_READ, NDMP_NO_ERR,
16927917SReza.Sabdar@Sun.COM 			    &request, 0) < 0) {
16937917SReza.Sabdar@Sun.COM 				NDMP_LOG(LOG_DEBUG,
16947917SReza.Sabdar@Sun.COM 				    "Sending notify_data_read request");
16957917SReza.Sabdar@Sun.COM 				return (-1);
16967917SReza.Sabdar@Sun.COM 			}
16977917SReza.Sabdar@Sun.COM 		}
16987917SReza.Sabdar@Sun.COM 
16997917SReza.Sabdar@Sun.COM 		/*
17007917SReza.Sabdar@Sun.COM 		 * If the module called ndmpd_seek() prior to reading all of the
17017917SReza.Sabdar@Sun.COM 		 * data that the remote mover was requested to send, then the
17027917SReza.Sabdar@Sun.COM 		 * excess data from the seek has to be discarded.
17037917SReza.Sabdar@Sun.COM 		 */
17047917SReza.Sabdar@Sun.COM 		if (session->ns_data.dd_discard_length != 0) {
17057917SReza.Sabdar@Sun.COM 			n = discard_data_v3(session,
17067917SReza.Sabdar@Sun.COM 			    (ulong_t)session->ns_data.dd_discard_length);
17077917SReza.Sabdar@Sun.COM 			if (n < 0)
17087917SReza.Sabdar@Sun.COM 				return (-1);
17097917SReza.Sabdar@Sun.COM 
17107917SReza.Sabdar@Sun.COM 			session->ns_data.dd_discard_length -= n;
17117917SReza.Sabdar@Sun.COM 			continue;
17127917SReza.Sabdar@Sun.COM 		}
17137917SReza.Sabdar@Sun.COM 
17147917SReza.Sabdar@Sun.COM 		/*
17157917SReza.Sabdar@Sun.COM 		 * Don't attempt to read more data than the remote is sending.
17167917SReza.Sabdar@Sun.COM 		 */
17177917SReza.Sabdar@Sun.COM 		if (len > session->ns_data.dd_bytes_left_to_read)
17187917SReza.Sabdar@Sun.COM 			len = session->ns_data.dd_bytes_left_to_read;
17197917SReza.Sabdar@Sun.COM 
17207917SReza.Sabdar@Sun.COM 		if ((n = read(session->ns_data.dd_sock, &data[count],
17217917SReza.Sabdar@Sun.COM 		    len)) < 0) {
17227917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_ERR, "Socket read error: %m.");
17237917SReza.Sabdar@Sun.COM 			return (-1);
17247917SReza.Sabdar@Sun.COM 		}
17257917SReza.Sabdar@Sun.COM 
17267917SReza.Sabdar@Sun.COM 		/* read returns 0 if the connection was closed */
17277917SReza.Sabdar@Sun.COM 		if (n == 0) {
17287917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG, "n 0 errno %d",
17297917SReza.Sabdar@Sun.COM 			    errno);
17307917SReza.Sabdar@Sun.COM 			return (-1);
17317917SReza.Sabdar@Sun.COM 		}
17327917SReza.Sabdar@Sun.COM 
17337917SReza.Sabdar@Sun.COM 		count += n;
17347917SReza.Sabdar@Sun.COM 		session->ns_data.dd_bytes_left_to_read -= n;
17357917SReza.Sabdar@Sun.COM 		session->ns_data.dd_position += n;
17367917SReza.Sabdar@Sun.COM 	}
17377917SReza.Sabdar@Sun.COM 	return (0);
17387917SReza.Sabdar@Sun.COM }
17397917SReza.Sabdar@Sun.COM 
17407917SReza.Sabdar@Sun.COM /*
17417917SReza.Sabdar@Sun.COM  * nlp_release_job_stat
17427917SReza.Sabdar@Sun.COM  *
17437917SReza.Sabdar@Sun.COM  * Unreference the job statistics
17447917SReza.Sabdar@Sun.COM  *
17457917SReza.Sabdar@Sun.COM  * Parameters:
17467917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
17477917SReza.Sabdar@Sun.COM  *
17487917SReza.Sabdar@Sun.COM  * Returns:
17497917SReza.Sabdar@Sun.COM  *   void
17507917SReza.Sabdar@Sun.COM  */
17517917SReza.Sabdar@Sun.COM static void
17527917SReza.Sabdar@Sun.COM nlp_release_job_stat(ndmpd_session_t *session)
17537917SReza.Sabdar@Sun.COM {
17547917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
17557917SReza.Sabdar@Sun.COM 
17567917SReza.Sabdar@Sun.COM 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
17577917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
17587917SReza.Sabdar@Sun.COM 		return;
17597917SReza.Sabdar@Sun.COM 	}
17607917SReza.Sabdar@Sun.COM 	if (nlp->nlp_jstat != NULL) {
17617917SReza.Sabdar@Sun.COM 		nlp->nlp_bytes_total =
17627917SReza.Sabdar@Sun.COM 		    (u_longlong_t)nlp->nlp_jstat->js_bytes_total;
17637917SReza.Sabdar@Sun.COM 		tlm_un_ref_job_stats(nlp->nlp_jstat->js_job_name);
17647917SReza.Sabdar@Sun.COM 		nlp->nlp_jstat = NULL;
17657917SReza.Sabdar@Sun.COM 	} else
17667917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "JSTAT == NULL");
17677917SReza.Sabdar@Sun.COM }
17687917SReza.Sabdar@Sun.COM 
17697917SReza.Sabdar@Sun.COM 
17707917SReza.Sabdar@Sun.COM /* *** ndmpd global internal functions *********************************** */
17717917SReza.Sabdar@Sun.COM 
17727917SReza.Sabdar@Sun.COM /*
17737917SReza.Sabdar@Sun.COM  * ndmpd_data_init
17747917SReza.Sabdar@Sun.COM  *
17757917SReza.Sabdar@Sun.COM  * Initializes data specific session variables.
17767917SReza.Sabdar@Sun.COM  *
17777917SReza.Sabdar@Sun.COM  * Parameters:
17787917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
17797917SReza.Sabdar@Sun.COM  *
17807917SReza.Sabdar@Sun.COM  * Returns:
17817917SReza.Sabdar@Sun.COM  *   void
17827917SReza.Sabdar@Sun.COM  */
17837917SReza.Sabdar@Sun.COM int
17847917SReza.Sabdar@Sun.COM ndmpd_data_init(ndmpd_session_t *session)
17857917SReza.Sabdar@Sun.COM {
17867917SReza.Sabdar@Sun.COM 	session->ns_data.dd_operation = NDMP_DATA_OP_NOACTION;
17877917SReza.Sabdar@Sun.COM 	session->ns_data.dd_state = NDMP_DATA_STATE_IDLE;
17887917SReza.Sabdar@Sun.COM 	session->ns_data.dd_halt_reason = NDMP_DATA_HALT_NA;
17897917SReza.Sabdar@Sun.COM 	session->ns_data.dd_abort = FALSE;
17907917SReza.Sabdar@Sun.COM 	session->ns_data.dd_env = 0;
17917917SReza.Sabdar@Sun.COM 	session->ns_data.dd_env_len = 0;
17927917SReza.Sabdar@Sun.COM 	session->ns_data.dd_nlist = 0;
17937917SReza.Sabdar@Sun.COM 	session->ns_data.dd_nlist_len = 0;
17947917SReza.Sabdar@Sun.COM 	session->ns_data.dd_mover.addr_type = NDMP_ADDR_LOCAL;
17957917SReza.Sabdar@Sun.COM 	session->ns_data.dd_sock = -1;
17967917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_offset = 0;
17977917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_length = 0;
17987917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_bytes_remaining = 0;
17997917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_time_remaining = 0;
18007917SReza.Sabdar@Sun.COM 	/*
18017917SReza.Sabdar@Sun.COM 	 * NDMP V3
18027917SReza.Sabdar@Sun.COM 	 */
18037917SReza.Sabdar@Sun.COM 	session->ns_data.dd_state = NDMP_DATA_STATE_IDLE;
18047917SReza.Sabdar@Sun.COM 	session->ns_data.dd_nlist_v3 = 0;
18057917SReza.Sabdar@Sun.COM 	session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_LOCAL;
18067917SReza.Sabdar@Sun.COM 	session->ns_data.dd_listen_sock = -1;
18077917SReza.Sabdar@Sun.COM 	session->ns_data.dd_bytes_left_to_read = 0LL;
18087917SReza.Sabdar@Sun.COM 	session->ns_data.dd_position = 0LL;
18097917SReza.Sabdar@Sun.COM 	session->ns_data.dd_discard_length = 0LL;
18107917SReza.Sabdar@Sun.COM 	return (0);
18117917SReza.Sabdar@Sun.COM }
18127917SReza.Sabdar@Sun.COM 
18137917SReza.Sabdar@Sun.COM 
18147917SReza.Sabdar@Sun.COM 
18157917SReza.Sabdar@Sun.COM /*
18167917SReza.Sabdar@Sun.COM  * ndmpd_data_cleanup
18177917SReza.Sabdar@Sun.COM  *
18187917SReza.Sabdar@Sun.COM  * Releases resources allocated during a data operation.
18197917SReza.Sabdar@Sun.COM  *
18207917SReza.Sabdar@Sun.COM  * Parameters:
18217917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
18227917SReza.Sabdar@Sun.COM  *
18237917SReza.Sabdar@Sun.COM  * Returns:
18247917SReza.Sabdar@Sun.COM  *   void
18257917SReza.Sabdar@Sun.COM  */
18267917SReza.Sabdar@Sun.COM void
18277917SReza.Sabdar@Sun.COM ndmpd_data_cleanup(ndmpd_session_t *session)
18287917SReza.Sabdar@Sun.COM {
18297917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_listen_sock != -1) {
18307917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "data.listen_sock: %d",
18317917SReza.Sabdar@Sun.COM 		    session->ns_data.dd_listen_sock);
18327917SReza.Sabdar@Sun.COM 		(void) ndmpd_remove_file_handler(session,
18337917SReza.Sabdar@Sun.COM 		    session->ns_data.dd_listen_sock);
18347917SReza.Sabdar@Sun.COM 		(void) close(session->ns_data.dd_listen_sock);
18357917SReza.Sabdar@Sun.COM 		session->ns_data.dd_listen_sock = -1;
18367917SReza.Sabdar@Sun.COM 	}
18377917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_sock != -1) {
18387917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "data.sock: %d",
18397917SReza.Sabdar@Sun.COM 		    session->ns_data.dd_sock);
18407917SReza.Sabdar@Sun.COM 
18417917SReza.Sabdar@Sun.COM 		/*
18427917SReza.Sabdar@Sun.COM 		 * ndmpcopy: we use the same socket for the mover,
18437917SReza.Sabdar@Sun.COM 		 * so expect to close when mover is done!
18447917SReza.Sabdar@Sun.COM 		 */
18457917SReza.Sabdar@Sun.COM 		if (session->ns_data.dd_sock != session->ns_mover.md_sock)
18467917SReza.Sabdar@Sun.COM 			(void) close(session->ns_data.dd_sock);
18477917SReza.Sabdar@Sun.COM 
18487917SReza.Sabdar@Sun.COM 		session->ns_data.dd_sock = -1;
18497917SReza.Sabdar@Sun.COM 	}
18507917SReza.Sabdar@Sun.COM 
18517917SReza.Sabdar@Sun.COM 	ndmpd_free_env(session);
18527917SReza.Sabdar@Sun.COM 	ndmpd_free_nlist(session);
18537917SReza.Sabdar@Sun.COM }
18547917SReza.Sabdar@Sun.COM 
18557917SReza.Sabdar@Sun.COM 
18567917SReza.Sabdar@Sun.COM /*
18577917SReza.Sabdar@Sun.COM  * ndmp_data_get_mover_mode
18587917SReza.Sabdar@Sun.COM  *
18597917SReza.Sabdar@Sun.COM  * Return the mover mode
18607917SReza.Sabdar@Sun.COM  *
18617917SReza.Sabdar@Sun.COM  * Parameters:
18627917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
18637917SReza.Sabdar@Sun.COM  *
18647917SReza.Sabdar@Sun.COM  * Returns:
18657917SReza.Sabdar@Sun.COM  *   remote - remote backup
18667917SReza.Sabdar@Sun.COM  *   local  - local backup
18677917SReza.Sabdar@Sun.COM  */
18687917SReza.Sabdar@Sun.COM char *
18697917SReza.Sabdar@Sun.COM ndmp_data_get_mover_mode(ndmpd_session_t *session)
18707917SReza.Sabdar@Sun.COM {
18717917SReza.Sabdar@Sun.COM 	char *rv;
18727917SReza.Sabdar@Sun.COM 
18737917SReza.Sabdar@Sun.COM 	switch (session->ns_protocol_version) {
18747917SReza.Sabdar@Sun.COM 	case NDMPV2:
18757917SReza.Sabdar@Sun.COM 		rv = ((session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP)
18767917SReza.Sabdar@Sun.COM 		    ? "remote" : "local");
18777917SReza.Sabdar@Sun.COM 		break;
18787917SReza.Sabdar@Sun.COM 	case NDMPV3:
18797917SReza.Sabdar@Sun.COM 		rv = ((session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_TCP)
18807917SReza.Sabdar@Sun.COM 		    ? "remote" : "local");
18817917SReza.Sabdar@Sun.COM 		break;
18827917SReza.Sabdar@Sun.COM 	case NDMPV4:
18837917SReza.Sabdar@Sun.COM 		rv = ((session->ns_data.dd_data_addr.addr_type ==
18847917SReza.Sabdar@Sun.COM 		    NDMP_ADDR_TCP ||
18857917SReza.Sabdar@Sun.COM 		    (session->ns_data.dd_data_addr_v4.addr_type ==
18867917SReza.Sabdar@Sun.COM 		    NDMP_ADDR_TCP)) ? "remote" : "local");
18877917SReza.Sabdar@Sun.COM 		break;
18887917SReza.Sabdar@Sun.COM 	default:
18897917SReza.Sabdar@Sun.COM 		rv = "Uknonwn";
18907917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid protocol version %d.",
18917917SReza.Sabdar@Sun.COM 		    session->ns_protocol_version);
18927917SReza.Sabdar@Sun.COM 	}
18937917SReza.Sabdar@Sun.COM 
18947917SReza.Sabdar@Sun.COM 	return (rv);
18957917SReza.Sabdar@Sun.COM }
18967917SReza.Sabdar@Sun.COM 
18977917SReza.Sabdar@Sun.COM /* *** static functions ******************************************** */
18987917SReza.Sabdar@Sun.COM 
18997917SReza.Sabdar@Sun.COM /*
19007917SReza.Sabdar@Sun.COM  * start_backup
19017917SReza.Sabdar@Sun.COM  *
19027917SReza.Sabdar@Sun.COM  * Request handling code common to version 1 and
19037917SReza.Sabdar@Sun.COM  * version 2 data_start_backup request handlers.
19047917SReza.Sabdar@Sun.COM  *
19057917SReza.Sabdar@Sun.COM  * Parameters:
19067917SReza.Sabdar@Sun.COM  *   session   (input) - session pointer.
19077917SReza.Sabdar@Sun.COM  *   bu_type   (input) - backup type.
19087917SReza.Sabdar@Sun.COM  *   env_val   (input) - environment variable array.
19097917SReza.Sabdar@Sun.COM  *   env_len   (input) - length of env_val.
19107917SReza.Sabdar@Sun.COM  *
19117917SReza.Sabdar@Sun.COM  * Returns:
19127917SReza.Sabdar@Sun.COM  *   NDMP_NO_ERR - backup successfully started.
19137917SReza.Sabdar@Sun.COM  *   otherwise - error code of backup start error.
19147917SReza.Sabdar@Sun.COM  */
19157917SReza.Sabdar@Sun.COM static ndmp_error
19167917SReza.Sabdar@Sun.COM start_backup(ndmpd_session_t *session, char *bu_type, ndmp_pval *env_val,
19177917SReza.Sabdar@Sun.COM     ulong_t env_len)
19187917SReza.Sabdar@Sun.COM {
19197917SReza.Sabdar@Sun.COM 	ndmp_data_start_backup_reply reply;
19207917SReza.Sabdar@Sun.COM 	ndmpd_module_params_t *params;
19217917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
19227917SReza.Sabdar@Sun.COM 	int err;
19237917SReza.Sabdar@Sun.COM 
19247917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
19257917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Can't start new backup in current state.");
19267917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_STATE_ERR);
19277917SReza.Sabdar@Sun.COM 	}
19287917SReza.Sabdar@Sun.COM 	if (strcmp(bu_type, NDMP_DUMP_TYPE) != 0 &&
19297917SReza.Sabdar@Sun.COM 	    strcmp(bu_type, NDMP_TAR_TYPE) != 0) {
19307917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid backup type: %s.", bu_type);
19317917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Supported backup types are tar and dump.");
19327917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
19337917SReza.Sabdar@Sun.COM 	}
19347917SReza.Sabdar@Sun.COM 	if ((err = ndmpd_save_env(session, env_val, env_len)) != NDMP_NO_ERR)
19357917SReza.Sabdar@Sun.COM 		return (err);
19367917SReza.Sabdar@Sun.COM 
19377917SReza.Sabdar@Sun.COM 	nlp = ndmp_get_nlp(session);
19387917SReza.Sabdar@Sun.COM 	NDMP_FREE(nlp->nlp_params);
19397917SReza.Sabdar@Sun.COM 	params = nlp->nlp_params = ndmp_malloc(sizeof (ndmpd_module_params_t));
19407917SReza.Sabdar@Sun.COM 	if (params == NULL)
19417917SReza.Sabdar@Sun.COM 		return (NDMP_NO_MEM_ERR);
19427917SReza.Sabdar@Sun.COM 
19437917SReza.Sabdar@Sun.COM 	params->mp_daemon_cookie = (void *)session;
19447917SReza.Sabdar@Sun.COM 	params->mp_module_cookie = &session->ns_data.dd_module.dm_module_cookie;
19457917SReza.Sabdar@Sun.COM 	params->mp_protocol_version = session->ns_protocol_version;
19467917SReza.Sabdar@Sun.COM 	params->mp_operation = NDMP_DATA_OP_BACKUP;
19477917SReza.Sabdar@Sun.COM 	params->mp_get_env_func = ndmpd_api_get_env;
19487917SReza.Sabdar@Sun.COM 	params->mp_add_env_func = ndmpd_api_add_env;
19497917SReza.Sabdar@Sun.COM 	params->mp_get_name_func = ndmpd_api_get_name;
19507917SReza.Sabdar@Sun.COM 	params->mp_dispatch_func = ndmpd_api_dispatch;
19517917SReza.Sabdar@Sun.COM 	params->mp_done_func = ndmpd_api_done_v2;
19527917SReza.Sabdar@Sun.COM 	params->mp_log_func = ndmpd_api_log_v2;
19537917SReza.Sabdar@Sun.COM 	params->mp_add_file_handler_func = ndmpd_api_add_file_handler;
19547917SReza.Sabdar@Sun.COM 	params->mp_remove_file_handler_func = ndmpd_api_remove_file_handler;
19557917SReza.Sabdar@Sun.COM 	params->mp_write_func = ndmpd_api_write_v2;
19567917SReza.Sabdar@Sun.COM 	params->mp_read_func = 0;
19577917SReza.Sabdar@Sun.COM 	params->mp_file_recovered_func = 0;
19587917SReza.Sabdar@Sun.COM 	params->mp_stats = &session->ns_data.dd_module.dm_stats;
19597917SReza.Sabdar@Sun.COM 
19607917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_module_cookie = 0;
19617917SReza.Sabdar@Sun.COM 	if (strcmp(bu_type, NDMP_DUMP_TYPE) == 0) {
19627917SReza.Sabdar@Sun.COM 		NLP_SET(nlp, NLPF_DUMP);
19637917SReza.Sabdar@Sun.COM 		params->mp_file_history_path_func = 0;
19647917SReza.Sabdar@Sun.COM 		params->mp_file_history_dir_func =
19657917SReza.Sabdar@Sun.COM 		    ndmpd_api_file_history_dir_v2;
19667917SReza.Sabdar@Sun.COM 		params->mp_file_history_node_func =
19677917SReza.Sabdar@Sun.COM 		    ndmpd_api_file_history_node_v2;
19687917SReza.Sabdar@Sun.COM 	} else if (strcmp(bu_type, NDMP_TAR_TYPE) == 0) {
19697917SReza.Sabdar@Sun.COM 		/* backup type == NDMP_TAR_TYPE */
19707917SReza.Sabdar@Sun.COM 		NLP_SET(nlp, NLPF_TAR);
19717917SReza.Sabdar@Sun.COM 		params->mp_file_history_path_func =
19727917SReza.Sabdar@Sun.COM 		    ndmpd_api_file_history_path_v2;
19737917SReza.Sabdar@Sun.COM 		params->mp_file_history_dir_func = 0;
19747917SReza.Sabdar@Sun.COM 		params->mp_file_history_node_func = 0;
19757917SReza.Sabdar@Sun.COM 	} else {
19767917SReza.Sabdar@Sun.COM 		NLP_UNSET(nlp, NLPF_DUMP);
19777917SReza.Sabdar@Sun.COM 		NLP_UNSET(nlp, NLPF_TAR);
19787917SReza.Sabdar@Sun.COM 	}
19797917SReza.Sabdar@Sun.COM 
19807917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_start_func = ndmpd_tar_backup_starter;
19817917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_abort_func = ndmpd_tar_backup_abort;
19827917SReza.Sabdar@Sun.COM 
19837917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_bytes_remaining = 0;
19847917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_time_remaining = 0;
19857917SReza.Sabdar@Sun.COM 	session->ns_data.dd_nlist = 0;
19867917SReza.Sabdar@Sun.COM 	session->ns_data.dd_nlist_len = 0;
19877917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_offset = 0;
19887917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_length = 0;
19897917SReza.Sabdar@Sun.COM 
19907917SReza.Sabdar@Sun.COM 	if ((err = ndmp_backup_extract_params(session,
19917917SReza.Sabdar@Sun.COM 	    params)) != NDMP_NO_ERR) {
19927917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "err: %d", err);
19937917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
19947917SReza.Sabdar@Sun.COM 		return (err);
19957917SReza.Sabdar@Sun.COM 	}
19967917SReza.Sabdar@Sun.COM 
19977917SReza.Sabdar@Sun.COM 	err = ndmpd_mover_connect(session, NDMP_MOVER_MODE_READ);
19987917SReza.Sabdar@Sun.COM 	if (err != NDMP_NO_ERR) {
19997917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
20007917SReza.Sabdar@Sun.COM 		    "mover connect err: %d", err);
20017917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
20027917SReza.Sabdar@Sun.COM 		return (err);
20037917SReza.Sabdar@Sun.COM 	}
20047917SReza.Sabdar@Sun.COM 
20057917SReza.Sabdar@Sun.COM 	session->ns_data.dd_state = NDMP_DATA_STATE_ACTIVE;
20067917SReza.Sabdar@Sun.COM 
20077917SReza.Sabdar@Sun.COM 	session->ns_data.dd_operation = NDMP_DATA_OP_BACKUP;
20087917SReza.Sabdar@Sun.COM 	session->ns_data.dd_abort = FALSE;
20097917SReza.Sabdar@Sun.COM 
20107917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "starting backup");
20117917SReza.Sabdar@Sun.COM 
20127917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
20137917SReza.Sabdar@Sun.COM 	if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
20147917SReza.Sabdar@Sun.COM 	    &reply) < 0) {
20157917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Sending data_start_backup reply");
20167917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
20177917SReza.Sabdar@Sun.COM 		if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
20187917SReza.Sabdar@Sun.COM 			/*
20197917SReza.Sabdar@Sun.COM 			 * ndmpcopy: we use the same socket for the mover,
20207917SReza.Sabdar@Sun.COM 			 * so expect to close when mover is done!
20217917SReza.Sabdar@Sun.COM 			 */
20227917SReza.Sabdar@Sun.COM 			if (session->ns_data.dd_sock !=
20237917SReza.Sabdar@Sun.COM 			    session->ns_mover.md_sock)
20247917SReza.Sabdar@Sun.COM 				(void) close(session->ns_data.dd_sock);
20257917SReza.Sabdar@Sun.COM 
20267917SReza.Sabdar@Sun.COM 			session->ns_data.dd_sock = -1;
20277917SReza.Sabdar@Sun.COM 		} else
20287917SReza.Sabdar@Sun.COM 			ndmpd_mover_error(session,
20297917SReza.Sabdar@Sun.COM 			    NDMP_MOVER_HALT_CONNECT_CLOSED);
20307917SReza.Sabdar@Sun.COM 		return (NDMP_NO_ERR);
20317917SReza.Sabdar@Sun.COM 	}
20327917SReza.Sabdar@Sun.COM 
20337917SReza.Sabdar@Sun.COM 	/*
20347917SReza.Sabdar@Sun.COM 	 * perform the backup
20357917SReza.Sabdar@Sun.COM 	 *
20367917SReza.Sabdar@Sun.COM 	 * Cannot wait for the thread to exit as we are replying to the
20377917SReza.Sabdar@Sun.COM 	 * client request here.
20387917SReza.Sabdar@Sun.COM 	 */
20397917SReza.Sabdar@Sun.COM 	(void) pthread_create(NULL, NULL,
20407917SReza.Sabdar@Sun.COM 	    (funct_t)session->ns_data.dd_module.dm_start_func,
20417917SReza.Sabdar@Sun.COM 	    params);
20427917SReza.Sabdar@Sun.COM 
20437917SReza.Sabdar@Sun.COM 	return (NDMP_NO_ERR);
20447917SReza.Sabdar@Sun.COM }
20457917SReza.Sabdar@Sun.COM 
20467917SReza.Sabdar@Sun.COM 
20477917SReza.Sabdar@Sun.COM /*
20487917SReza.Sabdar@Sun.COM  * start_recover
20497917SReza.Sabdar@Sun.COM  *
20507917SReza.Sabdar@Sun.COM  * The main recover/restore function
20517917SReza.Sabdar@Sun.COM  *
20527917SReza.Sabdar@Sun.COM  * Parameters:
20537917SReza.Sabdar@Sun.COM  *   session   (input) - session pointer.
20547917SReza.Sabdar@Sun.COM  *   bu_type   (input) - backup type.
20557917SReza.Sabdar@Sun.COM  *   env_val   (input) - environment variable array.
20567917SReza.Sabdar@Sun.COM  *   env_len   (input) - length of env_val.
20577917SReza.Sabdar@Sun.COM  *   nlist_val (input) - list of files
20587917SReza.Sabdar@Sun.COM  *   nlist_len (input) - length of nlist_val
20597917SReza.Sabdar@Sun.COM  *
20607917SReza.Sabdar@Sun.COM  * Returns:
20617917SReza.Sabdar@Sun.COM  *   NDMP_NO_ERR - recover successfully started.
20627917SReza.Sabdar@Sun.COM  *   otherwise - error code of backup start error.
20637917SReza.Sabdar@Sun.COM  */
20647917SReza.Sabdar@Sun.COM static ndmp_error
20657917SReza.Sabdar@Sun.COM start_recover(ndmpd_session_t *session, char *bu_type, ndmp_pval *env_val,
20667917SReza.Sabdar@Sun.COM     ulong_t env_len, ndmp_name *nlist_val, ulong_t nlist_len)
20677917SReza.Sabdar@Sun.COM {
20687917SReza.Sabdar@Sun.COM 	ndmp_data_start_recover_reply_v2 reply;
20697917SReza.Sabdar@Sun.COM 	ndmpd_module_params_t *params;
20707917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
20717917SReza.Sabdar@Sun.COM 	int err;
20727917SReza.Sabdar@Sun.COM 
20737917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
20747917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Can't start new recover in current state.");
20757917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_STATE_ERR);
20767917SReza.Sabdar@Sun.COM 	}
20777917SReza.Sabdar@Sun.COM 
20787917SReza.Sabdar@Sun.COM 	if (strcmp(bu_type, NDMP_DUMP_TYPE) != 0 &&
20797917SReza.Sabdar@Sun.COM 	    strcmp(bu_type, NDMP_TAR_TYPE) != 0) {
20807917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid backup type: %s.", bu_type);
20817917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Supported backup types are tar and dump.");
20827917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
20837917SReza.Sabdar@Sun.COM 	}
20847917SReza.Sabdar@Sun.COM 
20857917SReza.Sabdar@Sun.COM 	reply.error = ndmpd_save_env(session, env_val, env_len);
20867917SReza.Sabdar@Sun.COM 	if (reply.error != NDMP_NO_ERR)
20877917SReza.Sabdar@Sun.COM 		return (NDMP_NO_MEM_ERR);
20887917SReza.Sabdar@Sun.COM 
20897917SReza.Sabdar@Sun.COM 	reply.error = ndmpd_save_nlist_v2(session, nlist_val, nlist_len);
20907917SReza.Sabdar@Sun.COM 	if (reply.error != NDMP_NO_ERR)
20917917SReza.Sabdar@Sun.COM 		return (NDMP_NO_MEM_ERR);
20927917SReza.Sabdar@Sun.COM 
20937917SReza.Sabdar@Sun.COM 	nlp = ndmp_get_nlp(session);
20947917SReza.Sabdar@Sun.COM 	NDMP_FREE(nlp->nlp_params);
20957917SReza.Sabdar@Sun.COM 	params = nlp->nlp_params = ndmp_malloc(sizeof (ndmpd_module_params_t));
20967917SReza.Sabdar@Sun.COM 	if (params == NULL)
20977917SReza.Sabdar@Sun.COM 		return (NDMP_NO_MEM_ERR);
20987917SReza.Sabdar@Sun.COM 
20997917SReza.Sabdar@Sun.COM 	/*
21007917SReza.Sabdar@Sun.COM 	 * Setup restore parameters.
21017917SReza.Sabdar@Sun.COM 	 */
21027917SReza.Sabdar@Sun.COM 	params->mp_daemon_cookie = (void *)session;
21037917SReza.Sabdar@Sun.COM 	params->mp_module_cookie = &session->ns_data.dd_module.dm_module_cookie;
21047917SReza.Sabdar@Sun.COM 	params->mp_protocol_version = session->ns_protocol_version;
21057917SReza.Sabdar@Sun.COM 	params->mp_operation = NDMP_DATA_OP_RECOVER;
21067917SReza.Sabdar@Sun.COM 	params->mp_get_env_func = ndmpd_api_get_env;
21077917SReza.Sabdar@Sun.COM 	params->mp_add_env_func = ndmpd_api_add_env;
21087917SReza.Sabdar@Sun.COM 	params->mp_get_name_func = ndmpd_api_get_name;
21097917SReza.Sabdar@Sun.COM 	params->mp_dispatch_func = ndmpd_api_dispatch;
21107917SReza.Sabdar@Sun.COM 	params->mp_done_func = ndmpd_api_done_v2;
21117917SReza.Sabdar@Sun.COM 	params->mp_log_func = ndmpd_api_log_v2;
21127917SReza.Sabdar@Sun.COM 	params->mp_add_file_handler_func = ndmpd_api_add_file_handler;
21137917SReza.Sabdar@Sun.COM 	params->mp_remove_file_handler_func = ndmpd_api_remove_file_handler;
21147917SReza.Sabdar@Sun.COM 	params->mp_write_func = 0;
21157917SReza.Sabdar@Sun.COM 	params->mp_file_history_path_func = 0;
21167917SReza.Sabdar@Sun.COM 	params->mp_file_history_dir_func = 0;
21177917SReza.Sabdar@Sun.COM 	params->mp_file_history_node_func = 0;
21187917SReza.Sabdar@Sun.COM 	params->mp_read_func = ndmpd_api_read_v2;
21197917SReza.Sabdar@Sun.COM 	params->mp_seek_func = ndmpd_api_seek_v2;
21207917SReza.Sabdar@Sun.COM 	params->mp_file_recovered_func = ndmpd_api_file_recovered_v2;
21217917SReza.Sabdar@Sun.COM 	params->mp_stats = &session->ns_data.dd_module.dm_stats;
21227917SReza.Sabdar@Sun.COM 
21237917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_module_cookie = 0;
21247917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_start_func = ndmpd_tar_restore_starter;
21257917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_abort_func = ndmpd_tar_restore_abort;
21267917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_bytes_remaining = 0;
21277917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_time_remaining = 0;
21287917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_offset = 0;
21297917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_length = 0;
21307917SReza.Sabdar@Sun.COM 
21317917SReza.Sabdar@Sun.COM 	if ((err = ndmp_restore_extract_params(session,
21327917SReza.Sabdar@Sun.COM 	    params)) != NDMP_NO_ERR) {
21337917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
21347917SReza.Sabdar@Sun.COM 		return (err);
21357917SReza.Sabdar@Sun.COM 	}
21367917SReza.Sabdar@Sun.COM 
21377917SReza.Sabdar@Sun.COM 	err = ndmpd_mover_connect(session, NDMP_MOVER_MODE_WRITE);
21387917SReza.Sabdar@Sun.COM 	if (err != NDMP_NO_ERR) {
21397917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
21407917SReza.Sabdar@Sun.COM 		return (err);
21417917SReza.Sabdar@Sun.COM 	}
21427917SReza.Sabdar@Sun.COM 
21437917SReza.Sabdar@Sun.COM 	session->ns_data.dd_state = NDMP_DATA_STATE_ACTIVE;
21447917SReza.Sabdar@Sun.COM 	session->ns_data.dd_operation = NDMP_DATA_OP_RECOVER;
21457917SReza.Sabdar@Sun.COM 	session->ns_data.dd_abort = FALSE;
21467917SReza.Sabdar@Sun.COM 
21477917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
21487917SReza.Sabdar@Sun.COM 	if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
21497917SReza.Sabdar@Sun.COM 	    &reply) < 0) {
21507917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Sending data_start_recover reply");
21517917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
21527917SReza.Sabdar@Sun.COM 		if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
21537917SReza.Sabdar@Sun.COM 			/*
21547917SReza.Sabdar@Sun.COM 			 * ndmpcopy: we use the same socket for the mover,
21557917SReza.Sabdar@Sun.COM 			 * so expect to close when mover is done!
21567917SReza.Sabdar@Sun.COM 			 */
21577917SReza.Sabdar@Sun.COM 			if (session->ns_data.dd_sock !=
21587917SReza.Sabdar@Sun.COM 			    session->ns_mover.md_sock)
21597917SReza.Sabdar@Sun.COM 				(void) close(session->ns_data.dd_sock);
21607917SReza.Sabdar@Sun.COM 
21617917SReza.Sabdar@Sun.COM 			session->ns_data.dd_sock = -1;
21627917SReza.Sabdar@Sun.COM 		} else {
21637917SReza.Sabdar@Sun.COM 			ndmpd_mover_error(session,
21647917SReza.Sabdar@Sun.COM 			    NDMP_MOVER_HALT_CONNECT_CLOSED);
21657917SReza.Sabdar@Sun.COM 		}
21667917SReza.Sabdar@Sun.COM 		return (NDMP_NO_ERR);
21677917SReza.Sabdar@Sun.COM 	}
21687917SReza.Sabdar@Sun.COM 
21697917SReza.Sabdar@Sun.COM 
21707917SReza.Sabdar@Sun.COM 	/*
21717917SReza.Sabdar@Sun.COM 	 * perform the restore
21727917SReza.Sabdar@Sun.COM 	 *
21737917SReza.Sabdar@Sun.COM 	 * Cannot wait for the thread to exit as we are replying the
21747917SReza.Sabdar@Sun.COM 	 * client request here.
21757917SReza.Sabdar@Sun.COM 	 */
21767917SReza.Sabdar@Sun.COM 	(void) pthread_create(NULL, NULL,
21777917SReza.Sabdar@Sun.COM 	    (funct_t)session->ns_data.dd_module.dm_start_func,
21787917SReza.Sabdar@Sun.COM 	    params);
21797917SReza.Sabdar@Sun.COM 
21807917SReza.Sabdar@Sun.COM 	return (NDMP_NO_ERR);
21817917SReza.Sabdar@Sun.COM }
21827917SReza.Sabdar@Sun.COM 
21837917SReza.Sabdar@Sun.COM 
21847917SReza.Sabdar@Sun.COM /*
21857917SReza.Sabdar@Sun.COM  * ndmpd_data_get_info
21867917SReza.Sabdar@Sun.COM  *
21877917SReza.Sabdar@Sun.COM  * Return the total number of bytes processed
21887917SReza.Sabdar@Sun.COM  *
21897917SReza.Sabdar@Sun.COM  * Parameters:
21907917SReza.Sabdar@Sun.COM  *   session   (input) - session pointer.
21917917SReza.Sabdar@Sun.COM  *
21927917SReza.Sabdar@Sun.COM  * Returns:
21937917SReza.Sabdar@Sun.COM  *   the number of bytes processed
21947917SReza.Sabdar@Sun.COM  */
21957917SReza.Sabdar@Sun.COM static u_longlong_t
21967917SReza.Sabdar@Sun.COM ndmpd_data_get_info(ndmpd_session_t *session)
21977917SReza.Sabdar@Sun.COM {
21987917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
21997917SReza.Sabdar@Sun.COM 
22007917SReza.Sabdar@Sun.COM 	nlp = ndmp_get_nlp(session);
22017917SReza.Sabdar@Sun.COM 	if (nlp == NULL)
22027917SReza.Sabdar@Sun.COM 		return ((u_longlong_t)0);
22037917SReza.Sabdar@Sun.COM 
22047917SReza.Sabdar@Sun.COM 	if (nlp->nlp_jstat == NULL)
22057917SReza.Sabdar@Sun.COM 		return (nlp->nlp_bytes_total);
22067917SReza.Sabdar@Sun.COM 
22077917SReza.Sabdar@Sun.COM 	return ((u_longlong_t)nlp->nlp_jstat->js_bytes_total);
22087917SReza.Sabdar@Sun.COM }
2209