xref: /onnv-gate/usr/src/cmd/ndmpd/ndmp/ndmpd_data.c (revision 7917:5c4442486198)
1*7917SReza.Sabdar@Sun.COM /*
2*7917SReza.Sabdar@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3*7917SReza.Sabdar@Sun.COM  * Use is subject to license terms.
4*7917SReza.Sabdar@Sun.COM  */
5*7917SReza.Sabdar@Sun.COM 
6*7917SReza.Sabdar@Sun.COM /*
7*7917SReza.Sabdar@Sun.COM  * BSD 3 Clause License
8*7917SReza.Sabdar@Sun.COM  *
9*7917SReza.Sabdar@Sun.COM  * Copyright (c) 2007, The Storage Networking Industry Association.
10*7917SReza.Sabdar@Sun.COM  *
11*7917SReza.Sabdar@Sun.COM  * Redistribution and use in source and binary forms, with or without
12*7917SReza.Sabdar@Sun.COM  * modification, are permitted provided that the following conditions
13*7917SReza.Sabdar@Sun.COM  * are met:
14*7917SReza.Sabdar@Sun.COM  * 	- Redistributions of source code must retain the above copyright
15*7917SReza.Sabdar@Sun.COM  *	  notice, this list of conditions and the following disclaimer.
16*7917SReza.Sabdar@Sun.COM  *
17*7917SReza.Sabdar@Sun.COM  * 	- Redistributions in binary form must reproduce the above copyright
18*7917SReza.Sabdar@Sun.COM  *	  notice, this list of conditions and the following disclaimer in
19*7917SReza.Sabdar@Sun.COM  *	  the documentation and/or other materials provided with the
20*7917SReza.Sabdar@Sun.COM  *	  distribution.
21*7917SReza.Sabdar@Sun.COM  *
22*7917SReza.Sabdar@Sun.COM  *	- Neither the name of The Storage Networking Industry Association (SNIA)
23*7917SReza.Sabdar@Sun.COM  *	  nor the names of its contributors may be used to endorse or promote
24*7917SReza.Sabdar@Sun.COM  *	  products derived from this software without specific prior written
25*7917SReza.Sabdar@Sun.COM  *	  permission.
26*7917SReza.Sabdar@Sun.COM  *
27*7917SReza.Sabdar@Sun.COM  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28*7917SReza.Sabdar@Sun.COM  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29*7917SReza.Sabdar@Sun.COM  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30*7917SReza.Sabdar@Sun.COM  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31*7917SReza.Sabdar@Sun.COM  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32*7917SReza.Sabdar@Sun.COM  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33*7917SReza.Sabdar@Sun.COM  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34*7917SReza.Sabdar@Sun.COM  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35*7917SReza.Sabdar@Sun.COM  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36*7917SReza.Sabdar@Sun.COM  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37*7917SReza.Sabdar@Sun.COM  * POSSIBILITY OF SUCH DAMAGE.
38*7917SReza.Sabdar@Sun.COM  */
39*7917SReza.Sabdar@Sun.COM /* Copyright (c) 2007, The Storage Networking Industry Association. */
40*7917SReza.Sabdar@Sun.COM /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
41*7917SReza.Sabdar@Sun.COM 
42*7917SReza.Sabdar@Sun.COM #include <sys/types.h>
43*7917SReza.Sabdar@Sun.COM #include <sys/param.h>
44*7917SReza.Sabdar@Sun.COM #include <sys/socket.h>
45*7917SReza.Sabdar@Sun.COM #include <netinet/in.h>
46*7917SReza.Sabdar@Sun.COM #include <errno.h>
47*7917SReza.Sabdar@Sun.COM #include <arpa/inet.h>
48*7917SReza.Sabdar@Sun.COM #include <stdlib.h>
49*7917SReza.Sabdar@Sun.COM #include <string.h>
50*7917SReza.Sabdar@Sun.COM #include "ndmpd_common.h"
51*7917SReza.Sabdar@Sun.COM #include "ndmpd.h"
52*7917SReza.Sabdar@Sun.COM 
53*7917SReza.Sabdar@Sun.COM 
54*7917SReza.Sabdar@Sun.COM static int ndmpd_data_error_send_v4(ndmpd_session_t *session,
55*7917SReza.Sabdar@Sun.COM     ndmp_data_halt_reason reason);
56*7917SReza.Sabdar@Sun.COM static int ndmpd_data_error_send(ndmpd_session_t *session,
57*7917SReza.Sabdar@Sun.COM     ndmp_data_halt_reason reason);
58*7917SReza.Sabdar@Sun.COM static void data_accept_connection_v3(void *cookie, int fd, ulong_t mode);
59*7917SReza.Sabdar@Sun.COM static int create_listen_socket_v3(ndmpd_session_t *session, ulong_t *addr,
60*7917SReza.Sabdar@Sun.COM     ushort_t *port);
61*7917SReza.Sabdar@Sun.COM static ndmp_error data_connect_sock_v3(ndmpd_session_t *session, ulong_t addr,
62*7917SReza.Sabdar@Sun.COM     ushort_t port);
63*7917SReza.Sabdar@Sun.COM static int discard_data_v3(ndmpd_session_t *session, ulong_t length);
64*7917SReza.Sabdar@Sun.COM static void nlp_release_job_stat(ndmpd_session_t *session);
65*7917SReza.Sabdar@Sun.COM static u_longlong_t ndmpd_data_get_info(ndmpd_session_t *session);
66*7917SReza.Sabdar@Sun.COM static ndmp_error start_backup_v3(ndmpd_session_t *session, char *bu_type,
67*7917SReza.Sabdar@Sun.COM     ndmp_pval *env_val, ulong_t env_len);
68*7917SReza.Sabdar@Sun.COM static ndmp_error start_backup(ndmpd_session_t *session, char *bu_type,
69*7917SReza.Sabdar@Sun.COM     ndmp_pval *env_val, ulong_t env_len);
70*7917SReza.Sabdar@Sun.COM static ndmp_error start_recover(ndmpd_session_t *session, char *bu_type,
71*7917SReza.Sabdar@Sun.COM     ndmp_pval *env_val, ulong_t env_len, ndmp_name *nlist_val,
72*7917SReza.Sabdar@Sun.COM     ulong_t nlist_len);
73*7917SReza.Sabdar@Sun.COM static ndmp_error start_recover_v3(ndmpd_session_t *session, char *bu_type,
74*7917SReza.Sabdar@Sun.COM     ndmp_pval *env_val, ulong_t env_len, ndmp_name_v3 *nlist_val,
75*7917SReza.Sabdar@Sun.COM     ulong_t nlist_len);
76*7917SReza.Sabdar@Sun.COM static ndmp_error start_backup(ndmpd_session_t *session, char *bu_type,
77*7917SReza.Sabdar@Sun.COM     ndmp_pval *env_val, ulong_t env_len);
78*7917SReza.Sabdar@Sun.COM static ndmp_error start_recover(ndmpd_session_t *session, char *bu_type,
79*7917SReza.Sabdar@Sun.COM     ndmp_pval *env_val, ulong_t env_len, ndmp_name *nlist_val,
80*7917SReza.Sabdar@Sun.COM     ulong_t nlist_len);
81*7917SReza.Sabdar@Sun.COM static u_longlong_t ndmpd_data_get_info(ndmpd_session_t *session);
82*7917SReza.Sabdar@Sun.COM static void nlp_release_job_stat(ndmpd_session_t *session);
83*7917SReza.Sabdar@Sun.COM 
84*7917SReza.Sabdar@Sun.COM 
85*7917SReza.Sabdar@Sun.COM /*
86*7917SReza.Sabdar@Sun.COM  * ************************************************************************
87*7917SReza.Sabdar@Sun.COM  * NDMP V2 HANDLERS
88*7917SReza.Sabdar@Sun.COM  * ************************************************************************
89*7917SReza.Sabdar@Sun.COM  */
90*7917SReza.Sabdar@Sun.COM 
91*7917SReza.Sabdar@Sun.COM /*
92*7917SReza.Sabdar@Sun.COM  * ndmpd_data_get_state_v2
93*7917SReza.Sabdar@Sun.COM  *
94*7917SReza.Sabdar@Sun.COM  * Request handler. Returns current data state.
95*7917SReza.Sabdar@Sun.COM  *
96*7917SReza.Sabdar@Sun.COM  * Parameters:
97*7917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
98*7917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
99*7917SReza.Sabdar@Sun.COM  *
100*7917SReza.Sabdar@Sun.COM  * Returns:
101*7917SReza.Sabdar@Sun.COM  *   void
102*7917SReza.Sabdar@Sun.COM  */
103*7917SReza.Sabdar@Sun.COM /*ARGSUSED*/
104*7917SReza.Sabdar@Sun.COM void
105*7917SReza.Sabdar@Sun.COM ndmpd_data_get_state_v2(ndmp_connection_t *connection, void *body)
106*7917SReza.Sabdar@Sun.COM {
107*7917SReza.Sabdar@Sun.COM 	ndmp_data_get_state_reply_v2 reply;
108*7917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
109*7917SReza.Sabdar@Sun.COM 
110*7917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
111*7917SReza.Sabdar@Sun.COM 	reply.operation = session->ns_data.dd_operation;
112*7917SReza.Sabdar@Sun.COM 	reply.state = session->ns_data.dd_state;
113*7917SReza.Sabdar@Sun.COM 	reply.halt_reason = session->ns_data.dd_halt_reason;
114*7917SReza.Sabdar@Sun.COM 
115*7917SReza.Sabdar@Sun.COM 	reply.est_time_remain =
116*7917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_module.dm_stats.ms_est_time_remaining;
117*7917SReza.Sabdar@Sun.COM 	reply.est_bytes_remain =
118*7917SReza.Sabdar@Sun.COM 	    long_long_to_quad(
119*7917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_module.dm_stats.ms_est_bytes_remaining);
120*7917SReza.Sabdar@Sun.COM 
121*7917SReza.Sabdar@Sun.COM 	reply.bytes_processed =
122*7917SReza.Sabdar@Sun.COM 	    long_long_to_quad(ndmpd_data_get_info(session));
123*7917SReza.Sabdar@Sun.COM 
124*7917SReza.Sabdar@Sun.COM 	reply.mover = session->ns_data.dd_mover;
125*7917SReza.Sabdar@Sun.COM 	reply.read_offset = long_long_to_quad(session->ns_data.dd_read_offset);
126*7917SReza.Sabdar@Sun.COM 	reply.read_length = long_long_to_quad(session->ns_data.dd_read_length);
127*7917SReza.Sabdar@Sun.COM 
128*7917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
129*7917SReza.Sabdar@Sun.COM 	    "sending data_get_state reply");
130*7917SReza.Sabdar@Sun.COM }
131*7917SReza.Sabdar@Sun.COM 
132*7917SReza.Sabdar@Sun.COM 
133*7917SReza.Sabdar@Sun.COM /*
134*7917SReza.Sabdar@Sun.COM  * ndmpd_data_start_backup_v2
135*7917SReza.Sabdar@Sun.COM  *
136*7917SReza.Sabdar@Sun.COM  * Request handler. Starts a backup.
137*7917SReza.Sabdar@Sun.COM  *
138*7917SReza.Sabdar@Sun.COM  * Parameters:
139*7917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
140*7917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
141*7917SReza.Sabdar@Sun.COM  *
142*7917SReza.Sabdar@Sun.COM  * Returns:
143*7917SReza.Sabdar@Sun.COM  *   void
144*7917SReza.Sabdar@Sun.COM  */
145*7917SReza.Sabdar@Sun.COM void
146*7917SReza.Sabdar@Sun.COM ndmpd_data_start_backup_v2(ndmp_connection_t *connection, void *body)
147*7917SReza.Sabdar@Sun.COM {
148*7917SReza.Sabdar@Sun.COM 	ndmp_data_start_backup_request_v2 *request;
149*7917SReza.Sabdar@Sun.COM 	ndmp_data_start_backup_reply_v2 reply;
150*7917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
151*7917SReza.Sabdar@Sun.COM 	ndmp_error err;
152*7917SReza.Sabdar@Sun.COM 
153*7917SReza.Sabdar@Sun.COM 	request = (ndmp_data_start_backup_request_v2 *)body;
154*7917SReza.Sabdar@Sun.COM 
155*7917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
156*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_mover = request->mover;
157*7917SReza.Sabdar@Sun.COM 
158*7917SReza.Sabdar@Sun.COM 	err = start_backup(session, request->bu_type, request->env.env_val,
159*7917SReza.Sabdar@Sun.COM 	    request->env.env_len);
160*7917SReza.Sabdar@Sun.COM 
161*7917SReza.Sabdar@Sun.COM 	/*
162*7917SReza.Sabdar@Sun.COM 	 * start_backup sends the reply if the backup is successfully started.
163*7917SReza.Sabdar@Sun.COM 	 * Otherwise, send the reply containing the error here.
164*7917SReza.Sabdar@Sun.COM 	 */
165*7917SReza.Sabdar@Sun.COM 	if (err != NDMP_NO_ERR) {
166*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "err: %d", err);
167*7917SReza.Sabdar@Sun.COM 		reply.error = err;
168*7917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
169*7917SReza.Sabdar@Sun.COM 		    "sending data_start_backup reply");
170*7917SReza.Sabdar@Sun.COM 		ndmpd_data_cleanup(session);
171*7917SReza.Sabdar@Sun.COM 	}
172*7917SReza.Sabdar@Sun.COM }
173*7917SReza.Sabdar@Sun.COM 
174*7917SReza.Sabdar@Sun.COM 
175*7917SReza.Sabdar@Sun.COM /*
176*7917SReza.Sabdar@Sun.COM  * ndmpd_data_start_recover_v2
177*7917SReza.Sabdar@Sun.COM  *
178*7917SReza.Sabdar@Sun.COM  * Request handler. Starts a restore.
179*7917SReza.Sabdar@Sun.COM  *
180*7917SReza.Sabdar@Sun.COM  * Parameters:
181*7917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
182*7917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
183*7917SReza.Sabdar@Sun.COM  *
184*7917SReza.Sabdar@Sun.COM  * Returns:
185*7917SReza.Sabdar@Sun.COM  *   void
186*7917SReza.Sabdar@Sun.COM  */
187*7917SReza.Sabdar@Sun.COM void
188*7917SReza.Sabdar@Sun.COM ndmpd_data_start_recover_v2(ndmp_connection_t *connection, void *body)
189*7917SReza.Sabdar@Sun.COM {
190*7917SReza.Sabdar@Sun.COM 	ndmp_data_start_recover_request_v2 *request;
191*7917SReza.Sabdar@Sun.COM 	ndmp_data_start_recover_reply_v2 reply;
192*7917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
193*7917SReza.Sabdar@Sun.COM 	ndmp_error err;
194*7917SReza.Sabdar@Sun.COM 
195*7917SReza.Sabdar@Sun.COM 	request = (ndmp_data_start_recover_request_v2 *) body;
196*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_mover = request->mover;
197*7917SReza.Sabdar@Sun.COM 
198*7917SReza.Sabdar@Sun.COM 	err = start_recover(session, request->bu_type, request->env.env_val,
199*7917SReza.Sabdar@Sun.COM 	    request->env.env_len, request->nlist.nlist_val,
200*7917SReza.Sabdar@Sun.COM 	    request->nlist.nlist_len);
201*7917SReza.Sabdar@Sun.COM 	/*
202*7917SReza.Sabdar@Sun.COM 	 * start_recover sends the reply if the recover is successfully started.
203*7917SReza.Sabdar@Sun.COM 	 * Otherwise, send the reply containing the error here.
204*7917SReza.Sabdar@Sun.COM 	 */
205*7917SReza.Sabdar@Sun.COM 	if (err != NDMP_NO_ERR) {
206*7917SReza.Sabdar@Sun.COM 		reply.error = err;
207*7917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
208*7917SReza.Sabdar@Sun.COM 		    "sending ndmp_data_start_recover_request_v2 reply");
209*7917SReza.Sabdar@Sun.COM 		ndmpd_data_cleanup(session);
210*7917SReza.Sabdar@Sun.COM 	}
211*7917SReza.Sabdar@Sun.COM }
212*7917SReza.Sabdar@Sun.COM 
213*7917SReza.Sabdar@Sun.COM 
214*7917SReza.Sabdar@Sun.COM /*
215*7917SReza.Sabdar@Sun.COM  * ndmpd_data_get_env_v2
216*7917SReza.Sabdar@Sun.COM  *
217*7917SReza.Sabdar@Sun.COM  * Request handler. Returns the environment variable array sent
218*7917SReza.Sabdar@Sun.COM  * with the backup request. This request may only be sent with
219*7917SReza.Sabdar@Sun.COM  * a backup operation is in progress.
220*7917SReza.Sabdar@Sun.COM  *
221*7917SReza.Sabdar@Sun.COM  * Parameters:
222*7917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
223*7917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
224*7917SReza.Sabdar@Sun.COM  *
225*7917SReza.Sabdar@Sun.COM  * Returns:
226*7917SReza.Sabdar@Sun.COM  *   void
227*7917SReza.Sabdar@Sun.COM  */
228*7917SReza.Sabdar@Sun.COM /*ARGSUSED*/
229*7917SReza.Sabdar@Sun.COM void
230*7917SReza.Sabdar@Sun.COM ndmpd_data_get_env_v2(ndmp_connection_t *connection, void *body)
231*7917SReza.Sabdar@Sun.COM {
232*7917SReza.Sabdar@Sun.COM 	ndmp_data_get_env_reply reply;
233*7917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
234*7917SReza.Sabdar@Sun.COM 
235*7917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
236*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_operation != NDMP_DATA_OP_BACKUP) {
237*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Backup operation not active.");
238*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
239*7917SReza.Sabdar@Sun.COM 		reply.env.env_len = 0;
240*7917SReza.Sabdar@Sun.COM 	} else {
241*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
242*7917SReza.Sabdar@Sun.COM 		reply.env.env_len = session->ns_data.dd_env_len;
243*7917SReza.Sabdar@Sun.COM 		reply.env.env_val = session->ns_data.dd_env;
244*7917SReza.Sabdar@Sun.COM 	}
245*7917SReza.Sabdar@Sun.COM 
246*7917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply, "sending data_get_env reply");
247*7917SReza.Sabdar@Sun.COM }
248*7917SReza.Sabdar@Sun.COM 
249*7917SReza.Sabdar@Sun.COM 
250*7917SReza.Sabdar@Sun.COM /*
251*7917SReza.Sabdar@Sun.COM  * ndmpd_data_stop_v2
252*7917SReza.Sabdar@Sun.COM  *
253*7917SReza.Sabdar@Sun.COM  * Request handler. Stops the current data operation.
254*7917SReza.Sabdar@Sun.COM  *
255*7917SReza.Sabdar@Sun.COM  * Parameters:
256*7917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
257*7917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
258*7917SReza.Sabdar@Sun.COM  *
259*7917SReza.Sabdar@Sun.COM  * Returns:
260*7917SReza.Sabdar@Sun.COM  *   void
261*7917SReza.Sabdar@Sun.COM  */
262*7917SReza.Sabdar@Sun.COM /*ARGSUSED*/
263*7917SReza.Sabdar@Sun.COM void
264*7917SReza.Sabdar@Sun.COM ndmpd_data_stop_v2(ndmp_connection_t *connection, void *body)
265*7917SReza.Sabdar@Sun.COM {
266*7917SReza.Sabdar@Sun.COM 	ndmp_data_stop_reply reply;
267*7917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
268*7917SReza.Sabdar@Sun.COM 
269*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_HALTED) {
270*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid state to process stop request.");
271*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
272*7917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
273*7917SReza.Sabdar@Sun.COM 		    "sending data_stop reply");
274*7917SReza.Sabdar@Sun.COM 		return;
275*7917SReza.Sabdar@Sun.COM 	}
276*7917SReza.Sabdar@Sun.COM 	ndmp_waitfor_op(session);
277*7917SReza.Sabdar@Sun.COM 	ndmpd_data_cleanup(session);
278*7917SReza.Sabdar@Sun.COM 	ndmpd_file_history_cleanup(session, FALSE);
279*7917SReza.Sabdar@Sun.COM 
280*7917SReza.Sabdar@Sun.COM 	nlp_release_job_stat(session);
281*7917SReza.Sabdar@Sun.COM 
282*7917SReza.Sabdar@Sun.COM 	/* prepare for another data operation */
283*7917SReza.Sabdar@Sun.COM 	(void) ndmpd_data_init(session);
284*7917SReza.Sabdar@Sun.COM 	ndmpd_file_history_init(session);
285*7917SReza.Sabdar@Sun.COM 
286*7917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
287*7917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply, "sending data_stop reply");
288*7917SReza.Sabdar@Sun.COM }
289*7917SReza.Sabdar@Sun.COM 
290*7917SReza.Sabdar@Sun.COM 
291*7917SReza.Sabdar@Sun.COM /*
292*7917SReza.Sabdar@Sun.COM  * ndmpd_data_abort_v2
293*7917SReza.Sabdar@Sun.COM  *
294*7917SReza.Sabdar@Sun.COM  * Request handler. Aborts the current backup/restore. The operation
295*7917SReza.Sabdar@Sun.COM  * state is not changed to the halted state until after the operation
296*7917SReza.Sabdar@Sun.COM  * has actually been aborted and the notify_halt request has been sent.
297*7917SReza.Sabdar@Sun.COM  *
298*7917SReza.Sabdar@Sun.COM  * Parameters:
299*7917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
300*7917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
301*7917SReza.Sabdar@Sun.COM  *
302*7917SReza.Sabdar@Sun.COM  * Returns:
303*7917SReza.Sabdar@Sun.COM  *   void
304*7917SReza.Sabdar@Sun.COM  */
305*7917SReza.Sabdar@Sun.COM /*ARGSUSED*/
306*7917SReza.Sabdar@Sun.COM void
307*7917SReza.Sabdar@Sun.COM ndmpd_data_abort_v2(ndmp_connection_t *connection, void *body)
308*7917SReza.Sabdar@Sun.COM {
309*7917SReza.Sabdar@Sun.COM 	ndmp_data_abort_reply reply;
310*7917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
311*7917SReza.Sabdar@Sun.COM 
312*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state == NDMP_DATA_STATE_IDLE ||
313*7917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_state == NDMP_DATA_STATE_HALTED) {
314*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid state to process abort request.");
315*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
316*7917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
317*7917SReza.Sabdar@Sun.COM 		    "sending data_abort reply");
318*7917SReza.Sabdar@Sun.COM 		return;
319*7917SReza.Sabdar@Sun.COM 	}
320*7917SReza.Sabdar@Sun.COM 	/*
321*7917SReza.Sabdar@Sun.COM 	 * Don't go to HALTED state yet. Need to wait for data operation to
322*7917SReza.Sabdar@Sun.COM 	 * abort. When this happens, ndmpd_done will get called and will
323*7917SReza.Sabdar@Sun.COM 	 * perform the halt processing.
324*7917SReza.Sabdar@Sun.COM 	 */
325*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_abort = TRUE;
326*7917SReza.Sabdar@Sun.COM 	(*session->ns_data.dd_module.dm_abort_func)(
327*7917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_module.dm_module_cookie);
328*7917SReza.Sabdar@Sun.COM 
329*7917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
330*7917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply, "sending data_abort reply");
331*7917SReza.Sabdar@Sun.COM }
332*7917SReza.Sabdar@Sun.COM 
333*7917SReza.Sabdar@Sun.COM /*
334*7917SReza.Sabdar@Sun.COM  * ************************************************************************
335*7917SReza.Sabdar@Sun.COM  * NDMP V3 HANDLERS
336*7917SReza.Sabdar@Sun.COM  * ************************************************************************
337*7917SReza.Sabdar@Sun.COM  */
338*7917SReza.Sabdar@Sun.COM 
339*7917SReza.Sabdar@Sun.COM /*
340*7917SReza.Sabdar@Sun.COM  * ndmpd_data_get_state_v3
341*7917SReza.Sabdar@Sun.COM  *
342*7917SReza.Sabdar@Sun.COM  * Request handler. Returns current data state.
343*7917SReza.Sabdar@Sun.COM  *
344*7917SReza.Sabdar@Sun.COM  * Parameters:
345*7917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
346*7917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
347*7917SReza.Sabdar@Sun.COM  *
348*7917SReza.Sabdar@Sun.COM  * Returns:
349*7917SReza.Sabdar@Sun.COM  *   void
350*7917SReza.Sabdar@Sun.COM  */
351*7917SReza.Sabdar@Sun.COM /*ARGSUSED*/
352*7917SReza.Sabdar@Sun.COM void
353*7917SReza.Sabdar@Sun.COM ndmpd_data_get_state_v3(ndmp_connection_t *connection, void *body)
354*7917SReza.Sabdar@Sun.COM {
355*7917SReza.Sabdar@Sun.COM 	ndmp_data_get_state_reply_v3 reply;
356*7917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
357*7917SReza.Sabdar@Sun.COM 
358*7917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
359*7917SReza.Sabdar@Sun.COM 
360*7917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
361*7917SReza.Sabdar@Sun.COM 	reply.invalid = NDMP_DATA_STATE_EST_BYTES_REMAIN_INVALID
362*7917SReza.Sabdar@Sun.COM 	    | NDMP_DATA_STATE_EST_TIME_REMAIN_INVALID;
363*7917SReza.Sabdar@Sun.COM 	reply.operation = session->ns_data.dd_operation;
364*7917SReza.Sabdar@Sun.COM 	reply.state = session->ns_data.dd_state;
365*7917SReza.Sabdar@Sun.COM 	reply.halt_reason = session->ns_data.dd_halt_reason;
366*7917SReza.Sabdar@Sun.COM 
367*7917SReza.Sabdar@Sun.COM 	if (reply.operation == NDMP_DATA_OP_BACKUP)
368*7917SReza.Sabdar@Sun.COM 		reply.bytes_processed =
369*7917SReza.Sabdar@Sun.COM 		    long_long_to_quad(
370*7917SReza.Sabdar@Sun.COM 		    session->ns_data.dd_module.dm_stats.ms_bytes_processed);
371*7917SReza.Sabdar@Sun.COM 	else
372*7917SReza.Sabdar@Sun.COM 		reply.bytes_processed =
373*7917SReza.Sabdar@Sun.COM 		    long_long_to_quad(ndmpd_data_get_info(session));
374*7917SReza.Sabdar@Sun.COM 
375*7917SReza.Sabdar@Sun.COM 	reply.est_bytes_remain = long_long_to_quad(0LL);
376*7917SReza.Sabdar@Sun.COM 	reply.est_time_remain = 0;
377*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE)
378*7917SReza.Sabdar@Sun.COM 		ndmp_copy_addr_v3(&reply.data_connection_addr,
379*7917SReza.Sabdar@Sun.COM 		    &session->ns_data.dd_data_addr);
380*7917SReza.Sabdar@Sun.COM 	reply.read_offset = long_long_to_quad(session->ns_data.dd_read_offset);
381*7917SReza.Sabdar@Sun.COM 	reply.read_length = long_long_to_quad(session->ns_data.dd_read_length);
382*7917SReza.Sabdar@Sun.COM 
383*7917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
384*7917SReza.Sabdar@Sun.COM 	    "sending ndmp_data_get_state_v3 reply");
385*7917SReza.Sabdar@Sun.COM }
386*7917SReza.Sabdar@Sun.COM 
387*7917SReza.Sabdar@Sun.COM 
388*7917SReza.Sabdar@Sun.COM /*
389*7917SReza.Sabdar@Sun.COM  * ndmpd_data_start_backup_v3
390*7917SReza.Sabdar@Sun.COM  *
391*7917SReza.Sabdar@Sun.COM  * Request handler. Starts a backup.
392*7917SReza.Sabdar@Sun.COM  *
393*7917SReza.Sabdar@Sun.COM  * Parameters:
394*7917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
395*7917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
396*7917SReza.Sabdar@Sun.COM  *
397*7917SReza.Sabdar@Sun.COM  * Returns:
398*7917SReza.Sabdar@Sun.COM  *   void
399*7917SReza.Sabdar@Sun.COM  */
400*7917SReza.Sabdar@Sun.COM void
401*7917SReza.Sabdar@Sun.COM ndmpd_data_start_backup_v3(ndmp_connection_t *connection, void *body)
402*7917SReza.Sabdar@Sun.COM {
403*7917SReza.Sabdar@Sun.COM 	ndmp_data_start_backup_request_v3 *request;
404*7917SReza.Sabdar@Sun.COM 	ndmp_data_start_backup_reply_v3 reply;
405*7917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
406*7917SReza.Sabdar@Sun.COM 	ndmp_error err;
407*7917SReza.Sabdar@Sun.COM 
408*7917SReza.Sabdar@Sun.COM 	request = (ndmp_data_start_backup_request_v3 *)body;
409*7917SReza.Sabdar@Sun.COM 
410*7917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
411*7917SReza.Sabdar@Sun.COM 
412*7917SReza.Sabdar@Sun.COM 	err = start_backup_v3(session, request->bu_type, request->env.env_val,
413*7917SReza.Sabdar@Sun.COM 	    request->env.env_len);
414*7917SReza.Sabdar@Sun.COM 
415*7917SReza.Sabdar@Sun.COM 	/*
416*7917SReza.Sabdar@Sun.COM 	 * start_backup_v3 sends the reply if the backup is
417*7917SReza.Sabdar@Sun.COM 	 * successfully started.  Otherwise, send the reply
418*7917SReza.Sabdar@Sun.COM 	 * containing the error here.
419*7917SReza.Sabdar@Sun.COM 	 */
420*7917SReza.Sabdar@Sun.COM 	if (err != NDMP_NO_ERR) {
421*7917SReza.Sabdar@Sun.COM 		reply.error = err;
422*7917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
423*7917SReza.Sabdar@Sun.COM 		    "sending data_start_backup_v3 reply");
424*7917SReza.Sabdar@Sun.COM 		ndmpd_data_cleanup(session);
425*7917SReza.Sabdar@Sun.COM 	}
426*7917SReza.Sabdar@Sun.COM }
427*7917SReza.Sabdar@Sun.COM 
428*7917SReza.Sabdar@Sun.COM 
429*7917SReza.Sabdar@Sun.COM /*
430*7917SReza.Sabdar@Sun.COM  * ndmpd_data_start_recover_v3
431*7917SReza.Sabdar@Sun.COM  *
432*7917SReza.Sabdar@Sun.COM  * Request handler. Starts a restore.
433*7917SReza.Sabdar@Sun.COM  *
434*7917SReza.Sabdar@Sun.COM  * Parameters:
435*7917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
436*7917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
437*7917SReza.Sabdar@Sun.COM  *
438*7917SReza.Sabdar@Sun.COM  * Returns:
439*7917SReza.Sabdar@Sun.COM  *   void
440*7917SReza.Sabdar@Sun.COM  */
441*7917SReza.Sabdar@Sun.COM void
442*7917SReza.Sabdar@Sun.COM ndmpd_data_start_recover_v3(ndmp_connection_t *connection, void *body)
443*7917SReza.Sabdar@Sun.COM {
444*7917SReza.Sabdar@Sun.COM 	ndmp_data_start_recover_request_v3 *request;
445*7917SReza.Sabdar@Sun.COM 	ndmp_data_start_recover_reply_v3 reply;
446*7917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
447*7917SReza.Sabdar@Sun.COM 	ndmp_error err;
448*7917SReza.Sabdar@Sun.COM 
449*7917SReza.Sabdar@Sun.COM 	request = (ndmp_data_start_recover_request_v3 *)body;
450*7917SReza.Sabdar@Sun.COM 
451*7917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
452*7917SReza.Sabdar@Sun.COM 
453*7917SReza.Sabdar@Sun.COM 	err = start_recover_v3(session, request->bu_type, request->env.env_val,
454*7917SReza.Sabdar@Sun.COM 	    request->env.env_len, request->nlist.nlist_val,
455*7917SReza.Sabdar@Sun.COM 	    request->nlist.nlist_len);
456*7917SReza.Sabdar@Sun.COM 
457*7917SReza.Sabdar@Sun.COM 	/*
458*7917SReza.Sabdar@Sun.COM 	 * start_recover_v3 sends the reply if the recover is
459*7917SReza.Sabdar@Sun.COM 	 * successfully started.  Otherwise, send the reply
460*7917SReza.Sabdar@Sun.COM 	 * containing the error here.
461*7917SReza.Sabdar@Sun.COM 	 */
462*7917SReza.Sabdar@Sun.COM 	if (err != NDMP_NO_ERR) {
463*7917SReza.Sabdar@Sun.COM 		reply.error = err;
464*7917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
465*7917SReza.Sabdar@Sun.COM 		    "sending data_start_recover_v3 reply");
466*7917SReza.Sabdar@Sun.COM 		ndmpd_data_error(session, NDMP_DATA_HALT_INTERNAL_ERROR);
467*7917SReza.Sabdar@Sun.COM 		ndmpd_data_cleanup(session);
468*7917SReza.Sabdar@Sun.COM 	}
469*7917SReza.Sabdar@Sun.COM }
470*7917SReza.Sabdar@Sun.COM 
471*7917SReza.Sabdar@Sun.COM 
472*7917SReza.Sabdar@Sun.COM /*
473*7917SReza.Sabdar@Sun.COM  * ndmpd_data_abort_v3
474*7917SReza.Sabdar@Sun.COM  *
475*7917SReza.Sabdar@Sun.COM  * Request handler. Aborts the current backup/restore. The operation
476*7917SReza.Sabdar@Sun.COM  * state is not changed to the halted state until after the operation
477*7917SReza.Sabdar@Sun.COM  * has actually been aborted and the notify_halt request has been sent.
478*7917SReza.Sabdar@Sun.COM  *
479*7917SReza.Sabdar@Sun.COM  * Parameters:
480*7917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
481*7917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
482*7917SReza.Sabdar@Sun.COM  *
483*7917SReza.Sabdar@Sun.COM  * Returns:
484*7917SReza.Sabdar@Sun.COM  *   void
485*7917SReza.Sabdar@Sun.COM  */
486*7917SReza.Sabdar@Sun.COM /*ARGSUSED*/
487*7917SReza.Sabdar@Sun.COM void
488*7917SReza.Sabdar@Sun.COM ndmpd_data_abort_v3(ndmp_connection_t *connection, void *body)
489*7917SReza.Sabdar@Sun.COM {
490*7917SReza.Sabdar@Sun.COM 	ndmp_data_abort_reply reply;
491*7917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
492*7917SReza.Sabdar@Sun.COM 
493*7917SReza.Sabdar@Sun.COM 	switch (session->ns_data.dd_state) {
494*7917SReza.Sabdar@Sun.COM 	case NDMP_DATA_STATE_IDLE:
495*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
496*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid state to process abort request.");
497*7917SReza.Sabdar@Sun.COM 		break;
498*7917SReza.Sabdar@Sun.COM 
499*7917SReza.Sabdar@Sun.COM 	case NDMP_DATA_STATE_ACTIVE:
500*7917SReza.Sabdar@Sun.COM 		/*
501*7917SReza.Sabdar@Sun.COM 		 * Don't go to HALTED state yet.  Need to wait for data
502*7917SReza.Sabdar@Sun.COM 		 * operation to abort.  When this happens, ndmpd_done_v3
503*7917SReza.Sabdar@Sun.COM 		 * will get called and will perform the halt processing.
504*7917SReza.Sabdar@Sun.COM 		 */
505*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
506*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_abort = TRUE;
507*7917SReza.Sabdar@Sun.COM 		if (session->ns_data.dd_module.dm_abort_func)
508*7917SReza.Sabdar@Sun.COM 			(*session->ns_data.dd_module.dm_abort_func)(
509*7917SReza.Sabdar@Sun.COM 			    session->ns_data.dd_module.dm_module_cookie);
510*7917SReza.Sabdar@Sun.COM 		break;
511*7917SReza.Sabdar@Sun.COM 
512*7917SReza.Sabdar@Sun.COM 	case NDMP_DATA_STATE_HALTED:
513*7917SReza.Sabdar@Sun.COM 	case NDMP_DATA_STATE_LISTEN:
514*7917SReza.Sabdar@Sun.COM 	case NDMP_DATA_STATE_CONNECTED:
515*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
516*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_abort = TRUE;
517*7917SReza.Sabdar@Sun.COM 		ndmpd_data_error(session, NDMP_DATA_HALT_ABORTED);
518*7917SReza.Sabdar@Sun.COM 		break;
519*7917SReza.Sabdar@Sun.COM 	default:
520*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
521*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Unknown data V3 state %d",
522*7917SReza.Sabdar@Sun.COM 		    session->ns_data.dd_state);
523*7917SReza.Sabdar@Sun.COM 	}
524*7917SReza.Sabdar@Sun.COM 
525*7917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
526*7917SReza.Sabdar@Sun.COM 	    "sending data_abort_v3 reply");
527*7917SReza.Sabdar@Sun.COM }
528*7917SReza.Sabdar@Sun.COM 
529*7917SReza.Sabdar@Sun.COM 
530*7917SReza.Sabdar@Sun.COM /*
531*7917SReza.Sabdar@Sun.COM  * ndmpd_data_stop_v3
532*7917SReza.Sabdar@Sun.COM  *
533*7917SReza.Sabdar@Sun.COM  * Request handler. Stops the current data operation.
534*7917SReza.Sabdar@Sun.COM  *
535*7917SReza.Sabdar@Sun.COM  * Parameters:
536*7917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
537*7917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
538*7917SReza.Sabdar@Sun.COM  *
539*7917SReza.Sabdar@Sun.COM  * Returns:
540*7917SReza.Sabdar@Sun.COM  *   void
541*7917SReza.Sabdar@Sun.COM  */
542*7917SReza.Sabdar@Sun.COM /*ARGSUSED*/
543*7917SReza.Sabdar@Sun.COM void
544*7917SReza.Sabdar@Sun.COM ndmpd_data_stop_v3(ndmp_connection_t *connection, void *body)
545*7917SReza.Sabdar@Sun.COM {
546*7917SReza.Sabdar@Sun.COM 	ndmp_data_stop_reply reply;
547*7917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
548*7917SReza.Sabdar@Sun.COM 
549*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_HALTED) {
550*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid state to process stop request.");
551*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
552*7917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
553*7917SReza.Sabdar@Sun.COM 		    "sending data_stop_v3 reply");
554*7917SReza.Sabdar@Sun.COM 		return;
555*7917SReza.Sabdar@Sun.COM 	}
556*7917SReza.Sabdar@Sun.COM 	ndmp_waitfor_op(session);
557*7917SReza.Sabdar@Sun.COM 	ndmpd_data_cleanup(session);
558*7917SReza.Sabdar@Sun.COM 	ndmpd_file_history_cleanup(session, FALSE);
559*7917SReza.Sabdar@Sun.COM 
560*7917SReza.Sabdar@Sun.COM 	/* prepare for another data operation */
561*7917SReza.Sabdar@Sun.COM 	(void) ndmpd_data_init(session);
562*7917SReza.Sabdar@Sun.COM 	ndmpd_file_history_init(session);
563*7917SReza.Sabdar@Sun.COM 
564*7917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
565*7917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
566*7917SReza.Sabdar@Sun.COM 	    "sending data_stop_v3 reply");
567*7917SReza.Sabdar@Sun.COM }
568*7917SReza.Sabdar@Sun.COM 
569*7917SReza.Sabdar@Sun.COM 
570*7917SReza.Sabdar@Sun.COM /*
571*7917SReza.Sabdar@Sun.COM  * ndmpd_data_listen_v3
572*7917SReza.Sabdar@Sun.COM  *
573*7917SReza.Sabdar@Sun.COM  * Request handler. Configures the server to listen for a connection
574*7917SReza.Sabdar@Sun.COM  * from a remote mover.
575*7917SReza.Sabdar@Sun.COM  *
576*7917SReza.Sabdar@Sun.COM  * Parameters:
577*7917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
578*7917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
579*7917SReza.Sabdar@Sun.COM  *
580*7917SReza.Sabdar@Sun.COM  * Returns:
581*7917SReza.Sabdar@Sun.COM  *   void
582*7917SReza.Sabdar@Sun.COM  */
583*7917SReza.Sabdar@Sun.COM void
584*7917SReza.Sabdar@Sun.COM ndmpd_data_listen_v3(ndmp_connection_t *connection, void *body)
585*7917SReza.Sabdar@Sun.COM {
586*7917SReza.Sabdar@Sun.COM 	ndmp_data_listen_request_v3 *request;
587*7917SReza.Sabdar@Sun.COM 	ndmp_data_listen_reply_v3 reply;
588*7917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
589*7917SReza.Sabdar@Sun.COM 	ulong_t addr;
590*7917SReza.Sabdar@Sun.COM 	ushort_t port;
591*7917SReza.Sabdar@Sun.COM 
592*7917SReza.Sabdar@Sun.COM 	request = (ndmp_data_listen_request_v3 *)body;
593*7917SReza.Sabdar@Sun.COM 
594*7917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
595*7917SReza.Sabdar@Sun.COM 
596*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
597*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
598*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR,
599*7917SReza.Sabdar@Sun.COM 		    "Invalid internal data state to process listen request.");
600*7917SReza.Sabdar@Sun.COM 	} else if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) {
601*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
602*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR,
603*7917SReza.Sabdar@Sun.COM 		    "Invalid mover state to process listen request.");
604*7917SReza.Sabdar@Sun.COM 	} else {
605*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
606*7917SReza.Sabdar@Sun.COM 	}
607*7917SReza.Sabdar@Sun.COM 
608*7917SReza.Sabdar@Sun.COM 	if (reply.error != NDMP_NO_ERR) {
609*7917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
610*7917SReza.Sabdar@Sun.COM 		    "ndmp_data_listen_request_v3 reply");
611*7917SReza.Sabdar@Sun.COM 		return;
612*7917SReza.Sabdar@Sun.COM 	}
613*7917SReza.Sabdar@Sun.COM 
614*7917SReza.Sabdar@Sun.COM 	switch (request->addr_type) {
615*7917SReza.Sabdar@Sun.COM 	case NDMP_ADDR_LOCAL:
616*7917SReza.Sabdar@Sun.COM 		reply.data_connection_addr.addr_type = request->addr_type;
617*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_LOCAL;
618*7917SReza.Sabdar@Sun.COM 		break;
619*7917SReza.Sabdar@Sun.COM 	case NDMP_ADDR_TCP:
620*7917SReza.Sabdar@Sun.COM 		if (create_listen_socket_v3(session, &addr, &port) < 0) {
621*7917SReza.Sabdar@Sun.COM 			reply.error = NDMP_IO_ERR;
622*7917SReza.Sabdar@Sun.COM 			break;
623*7917SReza.Sabdar@Sun.COM 		}
624*7917SReza.Sabdar@Sun.COM 
625*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
626*7917SReza.Sabdar@Sun.COM 		reply.data_connection_addr.addr_type = request->addr_type;
627*7917SReza.Sabdar@Sun.COM 		reply.data_connection_addr.tcp_ip_v3 = htonl(addr);
628*7917SReza.Sabdar@Sun.COM 		reply.data_connection_addr.tcp_port_v3 = htons(port);
629*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_TCP;
630*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr.tcp_ip_v3 = addr;
631*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr.tcp_port_v3 = ntohs(port);
632*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "listen_socket: %d",
633*7917SReza.Sabdar@Sun.COM 		    session->ns_data.dd_listen_sock);
634*7917SReza.Sabdar@Sun.COM 		break;
635*7917SReza.Sabdar@Sun.COM 
636*7917SReza.Sabdar@Sun.COM 	default:
637*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Invalid address type: %d",
638*7917SReza.Sabdar@Sun.COM 		    request->addr_type);
639*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
640*7917SReza.Sabdar@Sun.COM 		break;
641*7917SReza.Sabdar@Sun.COM 	}
642*7917SReza.Sabdar@Sun.COM 
643*7917SReza.Sabdar@Sun.COM 	if (reply.error == NDMP_NO_ERR)
644*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_state = NDMP_DATA_STATE_LISTEN;
645*7917SReza.Sabdar@Sun.COM 
646*7917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
647*7917SReza.Sabdar@Sun.COM 	    "ndmp_data_listen_request_v3 reply");
648*7917SReza.Sabdar@Sun.COM }
649*7917SReza.Sabdar@Sun.COM 
650*7917SReza.Sabdar@Sun.COM 
651*7917SReza.Sabdar@Sun.COM /*
652*7917SReza.Sabdar@Sun.COM  * ndmpd_data_connect_v3
653*7917SReza.Sabdar@Sun.COM  *
654*7917SReza.Sabdar@Sun.COM  * Request handler. Connects the data server to either a local
655*7917SReza.Sabdar@Sun.COM  * or remote mover.
656*7917SReza.Sabdar@Sun.COM  *
657*7917SReza.Sabdar@Sun.COM  * Parameters:
658*7917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
659*7917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
660*7917SReza.Sabdar@Sun.COM  *
661*7917SReza.Sabdar@Sun.COM  * Returns:
662*7917SReza.Sabdar@Sun.COM  *   void
663*7917SReza.Sabdar@Sun.COM  */
664*7917SReza.Sabdar@Sun.COM void
665*7917SReza.Sabdar@Sun.COM ndmpd_data_connect_v3(ndmp_connection_t *connection, void *body)
666*7917SReza.Sabdar@Sun.COM {
667*7917SReza.Sabdar@Sun.COM 	ndmp_data_connect_request_v3 *request;
668*7917SReza.Sabdar@Sun.COM 	ndmp_data_connect_reply_v3 reply;
669*7917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
670*7917SReza.Sabdar@Sun.COM 
671*7917SReza.Sabdar@Sun.COM 	request = (ndmp_data_connect_request_v3 *)body;
672*7917SReza.Sabdar@Sun.COM 
673*7917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
674*7917SReza.Sabdar@Sun.COM 
675*7917SReza.Sabdar@Sun.COM 	if (!ndmp_valid_v3addr_type(request->addr.addr_type)) {
676*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
677*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Invalid address type %d",
678*7917SReza.Sabdar@Sun.COM 		    request->addr.addr_type);
679*7917SReza.Sabdar@Sun.COM 	} else if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
680*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
681*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid state to process connect request.");
682*7917SReza.Sabdar@Sun.COM 	} else {
683*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
684*7917SReza.Sabdar@Sun.COM 	}
685*7917SReza.Sabdar@Sun.COM 
686*7917SReza.Sabdar@Sun.COM 	if (reply.error != NDMP_NO_ERR) {
687*7917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
688*7917SReza.Sabdar@Sun.COM 		    "sending ndmp_data_connect_v3 reply");
689*7917SReza.Sabdar@Sun.COM 		return;
690*7917SReza.Sabdar@Sun.COM 	}
691*7917SReza.Sabdar@Sun.COM 
692*7917SReza.Sabdar@Sun.COM 	switch (request->addr.addr_type) {
693*7917SReza.Sabdar@Sun.COM 	case NDMP_ADDR_LOCAL:
694*7917SReza.Sabdar@Sun.COM 		/*
695*7917SReza.Sabdar@Sun.COM 		 * Verify that the mover is listening for a
696*7917SReza.Sabdar@Sun.COM 		 * local connection
697*7917SReza.Sabdar@Sun.COM 		 */
698*7917SReza.Sabdar@Sun.COM 		if (session->ns_mover.md_state != NDMP_MOVER_STATE_LISTEN ||
699*7917SReza.Sabdar@Sun.COM 		    session->ns_mover.md_listen_sock != -1) {
700*7917SReza.Sabdar@Sun.COM 			reply.error = NDMP_ILLEGAL_STATE_ERR;
701*7917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_ERR,
702*7917SReza.Sabdar@Sun.COM 			    "Mover is not in local listen state.");
703*7917SReza.Sabdar@Sun.COM 		} else {
704*7917SReza.Sabdar@Sun.COM 			session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE;
705*7917SReza.Sabdar@Sun.COM 		}
706*7917SReza.Sabdar@Sun.COM 		break;
707*7917SReza.Sabdar@Sun.COM 
708*7917SReza.Sabdar@Sun.COM 	case NDMP_ADDR_TCP:
709*7917SReza.Sabdar@Sun.COM 		reply.error = data_connect_sock_v3(session,
710*7917SReza.Sabdar@Sun.COM 		    request->addr.tcp_ip_v3, request->addr.tcp_port_v3);
711*7917SReza.Sabdar@Sun.COM 		break;
712*7917SReza.Sabdar@Sun.COM 
713*7917SReza.Sabdar@Sun.COM 	default:
714*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
715*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Invalid address type %d",
716*7917SReza.Sabdar@Sun.COM 		    request->addr.addr_type);
717*7917SReza.Sabdar@Sun.COM 	}
718*7917SReza.Sabdar@Sun.COM 
719*7917SReza.Sabdar@Sun.COM 	if (reply.error == NDMP_NO_ERR)
720*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_state = NDMP_DATA_STATE_CONNECTED;
721*7917SReza.Sabdar@Sun.COM 
722*7917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
723*7917SReza.Sabdar@Sun.COM 	    "sending ndmp_data_connect_v3 reply");
724*7917SReza.Sabdar@Sun.COM }
725*7917SReza.Sabdar@Sun.COM 
726*7917SReza.Sabdar@Sun.COM 
727*7917SReza.Sabdar@Sun.COM /*
728*7917SReza.Sabdar@Sun.COM  * ************************************************************************
729*7917SReza.Sabdar@Sun.COM  * NDMP V4 HANDLERS
730*7917SReza.Sabdar@Sun.COM  * ************************************************************************
731*7917SReza.Sabdar@Sun.COM  */
732*7917SReza.Sabdar@Sun.COM 
733*7917SReza.Sabdar@Sun.COM /*
734*7917SReza.Sabdar@Sun.COM  * ndmpd_data_get_env_v4
735*7917SReza.Sabdar@Sun.COM  *
736*7917SReza.Sabdar@Sun.COM  * Request handler. Returns the environment variable array sent
737*7917SReza.Sabdar@Sun.COM  * with the backup request. This request may only be sent with
738*7917SReza.Sabdar@Sun.COM  * a backup operation is in progress.
739*7917SReza.Sabdar@Sun.COM  *
740*7917SReza.Sabdar@Sun.COM  * Parameters:
741*7917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
742*7917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
743*7917SReza.Sabdar@Sun.COM  *
744*7917SReza.Sabdar@Sun.COM  * Returns:
745*7917SReza.Sabdar@Sun.COM  *   void
746*7917SReza.Sabdar@Sun.COM  */
747*7917SReza.Sabdar@Sun.COM /*ARGSUSED*/
748*7917SReza.Sabdar@Sun.COM void
749*7917SReza.Sabdar@Sun.COM ndmpd_data_get_env_v4(ndmp_connection_t *connection, void *body)
750*7917SReza.Sabdar@Sun.COM {
751*7917SReza.Sabdar@Sun.COM 	ndmp_data_get_env_reply reply;
752*7917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
753*7917SReza.Sabdar@Sun.COM 
754*7917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
755*7917SReza.Sabdar@Sun.COM 
756*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_ACTIVE &&
757*7917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_state != NDMP_DATA_STATE_HALTED) {
758*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid state for the data server.");
759*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
760*7917SReza.Sabdar@Sun.COM 		reply.env.env_len = 0;
761*7917SReza.Sabdar@Sun.COM 	} else if (session->ns_data.dd_operation != NDMP_DATA_OP_BACKUP) {
762*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Backup operation not active.");
763*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
764*7917SReza.Sabdar@Sun.COM 		reply.env.env_len = 0;
765*7917SReza.Sabdar@Sun.COM 	} else {
766*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
767*7917SReza.Sabdar@Sun.COM 		reply.env.env_len = session->ns_data.dd_env_len;
768*7917SReza.Sabdar@Sun.COM 		reply.env.env_val = session->ns_data.dd_env;
769*7917SReza.Sabdar@Sun.COM 	}
770*7917SReza.Sabdar@Sun.COM 
771*7917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply, "sending data_get_env reply");
772*7917SReza.Sabdar@Sun.COM }
773*7917SReza.Sabdar@Sun.COM 
774*7917SReza.Sabdar@Sun.COM /*
775*7917SReza.Sabdar@Sun.COM  * ndmpd_data_get_state_v4
776*7917SReza.Sabdar@Sun.COM  *
777*7917SReza.Sabdar@Sun.COM  * Request handler. Returns current data state.
778*7917SReza.Sabdar@Sun.COM  *
779*7917SReza.Sabdar@Sun.COM  * Parameters:
780*7917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
781*7917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
782*7917SReza.Sabdar@Sun.COM  *
783*7917SReza.Sabdar@Sun.COM  * Returns:
784*7917SReza.Sabdar@Sun.COM  *   void
785*7917SReza.Sabdar@Sun.COM  */
786*7917SReza.Sabdar@Sun.COM /*ARGSUSED*/
787*7917SReza.Sabdar@Sun.COM void
788*7917SReza.Sabdar@Sun.COM ndmpd_data_get_state_v4(ndmp_connection_t *connection, void *body)
789*7917SReza.Sabdar@Sun.COM {
790*7917SReza.Sabdar@Sun.COM 	ndmp_data_get_state_reply_v4 reply;
791*7917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
792*7917SReza.Sabdar@Sun.COM 
793*7917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
794*7917SReza.Sabdar@Sun.COM 
795*7917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
796*7917SReza.Sabdar@Sun.COM 	reply.unsupported = NDMP_DATA_STATE_EST_BYTES_REMAIN_INVALID
797*7917SReza.Sabdar@Sun.COM 	    | NDMP_DATA_STATE_EST_TIME_REMAIN_INVALID;
798*7917SReza.Sabdar@Sun.COM 	reply.operation = session->ns_data.dd_operation;
799*7917SReza.Sabdar@Sun.COM 	reply.state = session->ns_data.dd_state;
800*7917SReza.Sabdar@Sun.COM 	reply.halt_reason = session->ns_data.dd_halt_reason;
801*7917SReza.Sabdar@Sun.COM 
802*7917SReza.Sabdar@Sun.COM 	if (reply.operation == NDMP_DATA_OP_BACKUP)
803*7917SReza.Sabdar@Sun.COM 		reply.bytes_processed = long_long_to_quad(
804*7917SReza.Sabdar@Sun.COM 		    session->ns_data.dd_module.dm_stats.ms_bytes_processed);
805*7917SReza.Sabdar@Sun.COM 	else
806*7917SReza.Sabdar@Sun.COM 		reply.bytes_processed =
807*7917SReza.Sabdar@Sun.COM 		    long_long_to_quad(ndmpd_data_get_info(session));
808*7917SReza.Sabdar@Sun.COM 
809*7917SReza.Sabdar@Sun.COM 	reply.est_bytes_remain = long_long_to_quad(0LL);
810*7917SReza.Sabdar@Sun.COM 	reply.est_time_remain = 0;
811*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE)
812*7917SReza.Sabdar@Sun.COM 		ndmp_copy_addr_v4(&reply.data_connection_addr,
813*7917SReza.Sabdar@Sun.COM 		    &session->ns_data.dd_data_addr_v4);
814*7917SReza.Sabdar@Sun.COM 
815*7917SReza.Sabdar@Sun.COM 	reply.read_offset = long_long_to_quad(session->ns_data.dd_read_offset);
816*7917SReza.Sabdar@Sun.COM 	reply.read_length = long_long_to_quad(session->ns_data.dd_read_length);
817*7917SReza.Sabdar@Sun.COM 
818*7917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
819*7917SReza.Sabdar@Sun.COM 	    "sending ndmp_data_get_state_v4 reply");
820*7917SReza.Sabdar@Sun.COM 	free(reply.data_connection_addr.tcp_addr_v4);
821*7917SReza.Sabdar@Sun.COM }
822*7917SReza.Sabdar@Sun.COM 
823*7917SReza.Sabdar@Sun.COM 
824*7917SReza.Sabdar@Sun.COM /*
825*7917SReza.Sabdar@Sun.COM  * ndmpd_data_connect_v4
826*7917SReza.Sabdar@Sun.COM  *
827*7917SReza.Sabdar@Sun.COM  * Request handler. Connects the data server to either a local
828*7917SReza.Sabdar@Sun.COM  * or remote mover.
829*7917SReza.Sabdar@Sun.COM  *
830*7917SReza.Sabdar@Sun.COM  * Parameters:
831*7917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
832*7917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
833*7917SReza.Sabdar@Sun.COM  *
834*7917SReza.Sabdar@Sun.COM  * Returns:
835*7917SReza.Sabdar@Sun.COM  *   void
836*7917SReza.Sabdar@Sun.COM  */
837*7917SReza.Sabdar@Sun.COM void
838*7917SReza.Sabdar@Sun.COM ndmpd_data_connect_v4(ndmp_connection_t *connection, void *body)
839*7917SReza.Sabdar@Sun.COM {
840*7917SReza.Sabdar@Sun.COM 	ndmp_data_connect_request_v4 *request;
841*7917SReza.Sabdar@Sun.COM 	ndmp_data_connect_reply_v4 reply;
842*7917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
843*7917SReza.Sabdar@Sun.COM 
844*7917SReza.Sabdar@Sun.COM 	request = (ndmp_data_connect_request_v4 *)body;
845*7917SReza.Sabdar@Sun.COM 
846*7917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
847*7917SReza.Sabdar@Sun.COM 
848*7917SReza.Sabdar@Sun.COM 	if (!ndmp_valid_v3addr_type(request->addr.addr_type)) {
849*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
850*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Invalid address type %d",
851*7917SReza.Sabdar@Sun.COM 		    request->addr.addr_type);
852*7917SReza.Sabdar@Sun.COM 	} else if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
853*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
854*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid state to process connect request.");
855*7917SReza.Sabdar@Sun.COM 	} else {
856*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
857*7917SReza.Sabdar@Sun.COM 	}
858*7917SReza.Sabdar@Sun.COM 
859*7917SReza.Sabdar@Sun.COM 	if (reply.error != NDMP_NO_ERR) {
860*7917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
861*7917SReza.Sabdar@Sun.COM 		    "sending ndmp_data_connect_v4 reply");
862*7917SReza.Sabdar@Sun.COM 		return;
863*7917SReza.Sabdar@Sun.COM 	}
864*7917SReza.Sabdar@Sun.COM 
865*7917SReza.Sabdar@Sun.COM 	switch (request->addr.addr_type) {
866*7917SReza.Sabdar@Sun.COM 	case NDMP_ADDR_LOCAL:
867*7917SReza.Sabdar@Sun.COM 		/*
868*7917SReza.Sabdar@Sun.COM 		 * Verify that the mover is listening for a
869*7917SReza.Sabdar@Sun.COM 		 * local connection
870*7917SReza.Sabdar@Sun.COM 		 */
871*7917SReza.Sabdar@Sun.COM 		if (session->ns_mover.md_state != NDMP_MOVER_STATE_LISTEN ||
872*7917SReza.Sabdar@Sun.COM 		    session->ns_mover.md_listen_sock != -1) {
873*7917SReza.Sabdar@Sun.COM 			reply.error = NDMP_ILLEGAL_STATE_ERR;
874*7917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_ERR,
875*7917SReza.Sabdar@Sun.COM 			    "Mover is not in local listen state.");
876*7917SReza.Sabdar@Sun.COM 		} else {
877*7917SReza.Sabdar@Sun.COM 			session->ns_mover.md_state = NDMP_MOVER_STATE_ACTIVE;
878*7917SReza.Sabdar@Sun.COM 		}
879*7917SReza.Sabdar@Sun.COM 		break;
880*7917SReza.Sabdar@Sun.COM 
881*7917SReza.Sabdar@Sun.COM 	case NDMP_ADDR_TCP:
882*7917SReza.Sabdar@Sun.COM 		reply.error = data_connect_sock_v3(session,
883*7917SReza.Sabdar@Sun.COM 		    request->addr.tcp_ip_v4(0), request->addr.tcp_port_v4(0));
884*7917SReza.Sabdar@Sun.COM 		break;
885*7917SReza.Sabdar@Sun.COM 
886*7917SReza.Sabdar@Sun.COM 	default:
887*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
888*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Invalid address type %d",
889*7917SReza.Sabdar@Sun.COM 		    request->addr.addr_type);
890*7917SReza.Sabdar@Sun.COM 	}
891*7917SReza.Sabdar@Sun.COM 
892*7917SReza.Sabdar@Sun.COM 	if (reply.error == NDMP_NO_ERR)
893*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_state = NDMP_DATA_STATE_CONNECTED;
894*7917SReza.Sabdar@Sun.COM 
895*7917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
896*7917SReza.Sabdar@Sun.COM 	    "sending ndmp_data_connect_v4 reply");
897*7917SReza.Sabdar@Sun.COM }
898*7917SReza.Sabdar@Sun.COM 
899*7917SReza.Sabdar@Sun.COM /*
900*7917SReza.Sabdar@Sun.COM  * ndmpd_data_listen_v4
901*7917SReza.Sabdar@Sun.COM  *
902*7917SReza.Sabdar@Sun.COM  * Request handler. Configures the server to listen for a connection
903*7917SReza.Sabdar@Sun.COM  * from a remote mover.
904*7917SReza.Sabdar@Sun.COM  *
905*7917SReza.Sabdar@Sun.COM  * Parameters:
906*7917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
907*7917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
908*7917SReza.Sabdar@Sun.COM  *
909*7917SReza.Sabdar@Sun.COM  * Returns:
910*7917SReza.Sabdar@Sun.COM  *   void
911*7917SReza.Sabdar@Sun.COM  */
912*7917SReza.Sabdar@Sun.COM void
913*7917SReza.Sabdar@Sun.COM ndmpd_data_listen_v4(ndmp_connection_t *connection, void *body)
914*7917SReza.Sabdar@Sun.COM {
915*7917SReza.Sabdar@Sun.COM 	ndmp_data_listen_request_v4 *request;
916*7917SReza.Sabdar@Sun.COM 	ndmp_data_listen_reply_v4 reply;
917*7917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = ndmp_get_client_data(connection);
918*7917SReza.Sabdar@Sun.COM 	ulong_t addr;
919*7917SReza.Sabdar@Sun.COM 	ushort_t port;
920*7917SReza.Sabdar@Sun.COM 
921*7917SReza.Sabdar@Sun.COM 	request = (ndmp_data_listen_request_v4 *)body;
922*7917SReza.Sabdar@Sun.COM 
923*7917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
924*7917SReza.Sabdar@Sun.COM 
925*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
926*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
927*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR,
928*7917SReza.Sabdar@Sun.COM 		    "Invalid internal data state to process listen request.");
929*7917SReza.Sabdar@Sun.COM 	} else if (session->ns_mover.md_state != NDMP_MOVER_STATE_IDLE) {
930*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_STATE_ERR;
931*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR,
932*7917SReza.Sabdar@Sun.COM 		    "Invalid mover state to process listen request.");
933*7917SReza.Sabdar@Sun.COM 	} else {
934*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
935*7917SReza.Sabdar@Sun.COM 	}
936*7917SReza.Sabdar@Sun.COM 
937*7917SReza.Sabdar@Sun.COM 	if (reply.error != NDMP_NO_ERR) {
938*7917SReza.Sabdar@Sun.COM 		ndmp_send_reply(connection, &reply,
939*7917SReza.Sabdar@Sun.COM 		    "ndmp_data_listen_request_v4 reply");
940*7917SReza.Sabdar@Sun.COM 		return;
941*7917SReza.Sabdar@Sun.COM 	}
942*7917SReza.Sabdar@Sun.COM 
943*7917SReza.Sabdar@Sun.COM 	switch (request->addr_type) {
944*7917SReza.Sabdar@Sun.COM 	case NDMP_ADDR_LOCAL:
945*7917SReza.Sabdar@Sun.COM 		reply.connect_addr.addr_type = request->addr_type;
946*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_LOCAL;
947*7917SReza.Sabdar@Sun.COM 		break;
948*7917SReza.Sabdar@Sun.COM 	case NDMP_ADDR_TCP:
949*7917SReza.Sabdar@Sun.COM 		if (create_listen_socket_v3(session, &addr, &port) < 0) {
950*7917SReza.Sabdar@Sun.COM 			reply.error = NDMP_IO_ERR;
951*7917SReza.Sabdar@Sun.COM 			break;
952*7917SReza.Sabdar@Sun.COM 		}
953*7917SReza.Sabdar@Sun.COM 
954*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_NO_ERR;
955*7917SReza.Sabdar@Sun.COM 		reply.connect_addr.addr_type = request->addr_type;
956*7917SReza.Sabdar@Sun.COM 		reply.connect_addr.tcp_addr_v4 =
957*7917SReza.Sabdar@Sun.COM 		    ndmp_malloc(sizeof (ndmp_tcp_addr_v4));
958*7917SReza.Sabdar@Sun.COM 
959*7917SReza.Sabdar@Sun.COM 		reply.connect_addr.tcp_ip_v4(0) = htonl(addr);
960*7917SReza.Sabdar@Sun.COM 		reply.connect_addr.tcp_port_v4(0) = htons(port);
961*7917SReza.Sabdar@Sun.COM 		reply.connect_addr.tcp_len_v4 = 1;
962*7917SReza.Sabdar@Sun.COM 
963*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr_v4.addr_type = NDMP_ADDR_TCP;
964*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr_v4.tcp_addr_v4 =
965*7917SReza.Sabdar@Sun.COM 		    ndmp_malloc(sizeof (ndmp_tcp_addr_v4));
966*7917SReza.Sabdar@Sun.COM 
967*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr_v4.tcp_ip_v4(0) = addr;
968*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr_v4.tcp_port_v4(0) = ntohs(port);
969*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr_v4.tcp_len_v4 = 1;
970*7917SReza.Sabdar@Sun.COM 
971*7917SReza.Sabdar@Sun.COM 		/* Copy that to data_addr for compatibility */
972*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_TCP;
973*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr.tcp_ip_v3 = addr;
974*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_data_addr.tcp_port_v3 = ntohs(port);
975*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "listen_socket: %d",
976*7917SReza.Sabdar@Sun.COM 		    session->ns_data.dd_listen_sock);
977*7917SReza.Sabdar@Sun.COM 		break;
978*7917SReza.Sabdar@Sun.COM 
979*7917SReza.Sabdar@Sun.COM 	default:
980*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Invalid address type: %d",
981*7917SReza.Sabdar@Sun.COM 		    request->addr_type);
982*7917SReza.Sabdar@Sun.COM 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
983*7917SReza.Sabdar@Sun.COM 		break;
984*7917SReza.Sabdar@Sun.COM 	}
985*7917SReza.Sabdar@Sun.COM 
986*7917SReza.Sabdar@Sun.COM 	if (reply.error == NDMP_NO_ERR)
987*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_state = NDMP_DATA_STATE_LISTEN;
988*7917SReza.Sabdar@Sun.COM 
989*7917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
990*7917SReza.Sabdar@Sun.COM 	    "ndmp_data_listen_request_v4 reply");
991*7917SReza.Sabdar@Sun.COM }
992*7917SReza.Sabdar@Sun.COM 
993*7917SReza.Sabdar@Sun.COM 
994*7917SReza.Sabdar@Sun.COM /*
995*7917SReza.Sabdar@Sun.COM  * ndmpd_data_start_recover_filehist_v4
996*7917SReza.Sabdar@Sun.COM  *
997*7917SReza.Sabdar@Sun.COM  * Request handler. Recovers the file history (not supported yet)
998*7917SReza.Sabdar@Sun.COM  * This command has an optional support in V4.
999*7917SReza.Sabdar@Sun.COM  *
1000*7917SReza.Sabdar@Sun.COM  * Parameters:
1001*7917SReza.Sabdar@Sun.COM  *   connection (input) - connection handle.
1002*7917SReza.Sabdar@Sun.COM  *   body       (input) - request message body.
1003*7917SReza.Sabdar@Sun.COM  *
1004*7917SReza.Sabdar@Sun.COM  * Returns:
1005*7917SReza.Sabdar@Sun.COM  *   void
1006*7917SReza.Sabdar@Sun.COM  */
1007*7917SReza.Sabdar@Sun.COM /*ARGSUSED*/
1008*7917SReza.Sabdar@Sun.COM void
1009*7917SReza.Sabdar@Sun.COM ndmpd_data_start_recover_filehist_v4(ndmp_connection_t *connection, void *body)
1010*7917SReza.Sabdar@Sun.COM {
1011*7917SReza.Sabdar@Sun.COM 	ndmp_data_start_recover_filehist_reply_v4 reply;
1012*7917SReza.Sabdar@Sun.COM 
1013*7917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "Request not supported");
1014*7917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NOT_SUPPORTED_ERR;
1015*7917SReza.Sabdar@Sun.COM 
1016*7917SReza.Sabdar@Sun.COM 	ndmp_send_reply(connection, &reply,
1017*7917SReza.Sabdar@Sun.COM 	    "sending ndmp_data_start_recover_filehist_reply_v4 reply");
1018*7917SReza.Sabdar@Sun.COM }
1019*7917SReza.Sabdar@Sun.COM 
1020*7917SReza.Sabdar@Sun.COM /*
1021*7917SReza.Sabdar@Sun.COM  * ************************************************************************
1022*7917SReza.Sabdar@Sun.COM  * LOCALS
1023*7917SReza.Sabdar@Sun.COM  * ************************************************************************
1024*7917SReza.Sabdar@Sun.COM  */
1025*7917SReza.Sabdar@Sun.COM 
1026*7917SReza.Sabdar@Sun.COM /*
1027*7917SReza.Sabdar@Sun.COM  * ndmpd_data_error_send
1028*7917SReza.Sabdar@Sun.COM  *
1029*7917SReza.Sabdar@Sun.COM  * This function sends the notify message to the client.
1030*7917SReza.Sabdar@Sun.COM  *
1031*7917SReza.Sabdar@Sun.COM  * Parameters:
1032*7917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
1033*7917SReza.Sabdar@Sun.COM  *   reason  (input) - halt reason.
1034*7917SReza.Sabdar@Sun.COM  *
1035*7917SReza.Sabdar@Sun.COM  * Returns:
1036*7917SReza.Sabdar@Sun.COM  *   Error code
1037*7917SReza.Sabdar@Sun.COM  */
1038*7917SReza.Sabdar@Sun.COM /*ARGSUSED*/
1039*7917SReza.Sabdar@Sun.COM static int
1040*7917SReza.Sabdar@Sun.COM ndmpd_data_error_send(ndmpd_session_t *session, ndmp_data_halt_reason reason)
1041*7917SReza.Sabdar@Sun.COM {
1042*7917SReza.Sabdar@Sun.COM 	ndmp_notify_data_halted_request req;
1043*7917SReza.Sabdar@Sun.COM 
1044*7917SReza.Sabdar@Sun.COM 	req.reason = session->ns_data.dd_halt_reason;
1045*7917SReza.Sabdar@Sun.COM 	req.text_reason = "";
1046*7917SReza.Sabdar@Sun.COM 
1047*7917SReza.Sabdar@Sun.COM 	return (ndmp_send_request(session->ns_connection,
1048*7917SReza.Sabdar@Sun.COM 	    NDMP_NOTIFY_DATA_HALTED, NDMP_NO_ERR, &req, 0));
1049*7917SReza.Sabdar@Sun.COM }
1050*7917SReza.Sabdar@Sun.COM 
1051*7917SReza.Sabdar@Sun.COM 
1052*7917SReza.Sabdar@Sun.COM /*
1053*7917SReza.Sabdar@Sun.COM  * ndmpd_data_error_send_v4
1054*7917SReza.Sabdar@Sun.COM  *
1055*7917SReza.Sabdar@Sun.COM  * This function sends the notify message to the client.
1056*7917SReza.Sabdar@Sun.COM  *
1057*7917SReza.Sabdar@Sun.COM  * Parameters:
1058*7917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
1059*7917SReza.Sabdar@Sun.COM  *   reason  (input) - halt reason.
1060*7917SReza.Sabdar@Sun.COM  *
1061*7917SReza.Sabdar@Sun.COM  * Returns:
1062*7917SReza.Sabdar@Sun.COM  *   Error code
1063*7917SReza.Sabdar@Sun.COM  */
1064*7917SReza.Sabdar@Sun.COM /*ARGSUSED*/
1065*7917SReza.Sabdar@Sun.COM static int
1066*7917SReza.Sabdar@Sun.COM ndmpd_data_error_send_v4(ndmpd_session_t *session, ndmp_data_halt_reason reason)
1067*7917SReza.Sabdar@Sun.COM {
1068*7917SReza.Sabdar@Sun.COM 	ndmp_notify_data_halted_request_v4 req;
1069*7917SReza.Sabdar@Sun.COM 
1070*7917SReza.Sabdar@Sun.COM 	req.reason = session->ns_data.dd_halt_reason;
1071*7917SReza.Sabdar@Sun.COM 
1072*7917SReza.Sabdar@Sun.COM 	return ndmp_send_request(session->ns_connection,
1073*7917SReza.Sabdar@Sun.COM 	    NDMP_NOTIFY_DATA_HALTED, NDMP_NO_ERR, &req, 0);
1074*7917SReza.Sabdar@Sun.COM }
1075*7917SReza.Sabdar@Sun.COM 
1076*7917SReza.Sabdar@Sun.COM 
1077*7917SReza.Sabdar@Sun.COM /*
1078*7917SReza.Sabdar@Sun.COM  * ndmpd_data_error
1079*7917SReza.Sabdar@Sun.COM  *
1080*7917SReza.Sabdar@Sun.COM  * This function is called when a data error has been detected.
1081*7917SReza.Sabdar@Sun.COM  * A notify message is sent to the client and the data server is
1082*7917SReza.Sabdar@Sun.COM  * placed into the halted state.
1083*7917SReza.Sabdar@Sun.COM  *
1084*7917SReza.Sabdar@Sun.COM  * Parameters:
1085*7917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
1086*7917SReza.Sabdar@Sun.COM  *   reason  (input) - halt reason.
1087*7917SReza.Sabdar@Sun.COM  *
1088*7917SReza.Sabdar@Sun.COM  * Returns:
1089*7917SReza.Sabdar@Sun.COM  *   void
1090*7917SReza.Sabdar@Sun.COM  */
1091*7917SReza.Sabdar@Sun.COM void
1092*7917SReza.Sabdar@Sun.COM ndmpd_data_error(ndmpd_session_t *session, ndmp_data_halt_reason reason)
1093*7917SReza.Sabdar@Sun.COM {
1094*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state == NDMP_DATA_STATE_IDLE ||
1095*7917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_state == NDMP_DATA_STATE_HALTED)
1096*7917SReza.Sabdar@Sun.COM 		return;
1097*7917SReza.Sabdar@Sun.COM 
1098*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_operation == NDMP_DATA_OP_BACKUP) {
1099*7917SReza.Sabdar@Sun.COM 		/*
1100*7917SReza.Sabdar@Sun.COM 		 * Send/discard any buffered file history data.
1101*7917SReza.Sabdar@Sun.COM 		 */
1102*7917SReza.Sabdar@Sun.COM 		ndmpd_file_history_cleanup(session,
1103*7917SReza.Sabdar@Sun.COM 		    (reason == NDMP_DATA_HALT_SUCCESSFUL ? TRUE : FALSE));
1104*7917SReza.Sabdar@Sun.COM 
1105*7917SReza.Sabdar@Sun.COM 		/*
1106*7917SReza.Sabdar@Sun.COM 		 * If mover local and successful backup, write any
1107*7917SReza.Sabdar@Sun.COM 		 * remaining buffered data to tape.
1108*7917SReza.Sabdar@Sun.COM 		 */
1109*7917SReza.Sabdar@Sun.COM 		if (session->ns_data.dd_data_addr.addr_type
1110*7917SReza.Sabdar@Sun.COM 		    == NDMP_ADDR_LOCAL && reason == NDMP_DATA_HALT_SUCCESSFUL)
1111*7917SReza.Sabdar@Sun.COM 			(void) ndmpd_local_write_v3(session, 0, 0);
1112*7917SReza.Sabdar@Sun.COM 	}
1113*7917SReza.Sabdar@Sun.COM 
1114*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_state = NDMP_DATA_STATE_HALTED;
1115*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_halt_reason = reason;
1116*7917SReza.Sabdar@Sun.COM 
1117*7917SReza.Sabdar@Sun.COM 	if (session->ns_protocol_version == NDMPV4) {
1118*7917SReza.Sabdar@Sun.COM 		if (ndmpd_data_error_send_v4(session, reason) < 0)
1119*7917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG,
1120*7917SReza.Sabdar@Sun.COM 			    "Error sending notify_data_halted request");
1121*7917SReza.Sabdar@Sun.COM 	} else {
1122*7917SReza.Sabdar@Sun.COM 		if (ndmpd_data_error_send(session, reason) < 0)
1123*7917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG,
1124*7917SReza.Sabdar@Sun.COM 			    "Error sending notify_data_halted request");
1125*7917SReza.Sabdar@Sun.COM 	}
1126*7917SReza.Sabdar@Sun.COM 
1127*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_TCP) {
1128*7917SReza.Sabdar@Sun.COM 		if (session->ns_data.dd_sock != -1) {
1129*7917SReza.Sabdar@Sun.COM 			(void) ndmpd_remove_file_handler(session,
1130*7917SReza.Sabdar@Sun.COM 			    session->ns_data.dd_sock);
1131*7917SReza.Sabdar@Sun.COM 			/*
1132*7917SReza.Sabdar@Sun.COM 			 * ndmpcopy: we use the same socket for the mover,
1133*7917SReza.Sabdar@Sun.COM 			 * so expect to close when mover is done!
1134*7917SReza.Sabdar@Sun.COM 			 */
1135*7917SReza.Sabdar@Sun.COM 			if (session->ns_data.dd_sock !=
1136*7917SReza.Sabdar@Sun.COM 			    session->ns_mover.md_sock)
1137*7917SReza.Sabdar@Sun.COM 				(void) close(session->ns_data.dd_sock);
1138*7917SReza.Sabdar@Sun.COM 
1139*7917SReza.Sabdar@Sun.COM 			session->ns_data.dd_sock = -1;
1140*7917SReza.Sabdar@Sun.COM 		}
1141*7917SReza.Sabdar@Sun.COM 		if (session->ns_data.dd_listen_sock != -1) {
1142*7917SReza.Sabdar@Sun.COM 			(void) ndmpd_remove_file_handler(session,
1143*7917SReza.Sabdar@Sun.COM 			    session->ns_data.dd_listen_sock);
1144*7917SReza.Sabdar@Sun.COM 
1145*7917SReza.Sabdar@Sun.COM 			(void) close(session->ns_data.dd_listen_sock);
1146*7917SReza.Sabdar@Sun.COM 			session->ns_data.dd_listen_sock = -1;
1147*7917SReza.Sabdar@Sun.COM 		}
1148*7917SReza.Sabdar@Sun.COM 	} else {
1149*7917SReza.Sabdar@Sun.COM 		ndmpd_mover_error(session, NDMP_MOVER_HALT_CONNECT_CLOSED);
1150*7917SReza.Sabdar@Sun.COM 	}
1151*7917SReza.Sabdar@Sun.COM }
1152*7917SReza.Sabdar@Sun.COM 
1153*7917SReza.Sabdar@Sun.COM 
1154*7917SReza.Sabdar@Sun.COM /*
1155*7917SReza.Sabdar@Sun.COM  * data_accept_connection_v3
1156*7917SReza.Sabdar@Sun.COM  *
1157*7917SReza.Sabdar@Sun.COM  * Accept a data connection from a remote mover.
1158*7917SReza.Sabdar@Sun.COM  * Called by ndmpd_select when a connection is pending on
1159*7917SReza.Sabdar@Sun.COM  * the data listen socket.
1160*7917SReza.Sabdar@Sun.COM  *
1161*7917SReza.Sabdar@Sun.COM  * Parameters:
1162*7917SReza.Sabdar@Sun.COM  *   cookie  (input) - session pointer.
1163*7917SReza.Sabdar@Sun.COM  *   fd      (input) - file descriptor.
1164*7917SReza.Sabdar@Sun.COM  *   mode    (input) - select mode.
1165*7917SReza.Sabdar@Sun.COM  *
1166*7917SReza.Sabdar@Sun.COM  * Returns:
1167*7917SReza.Sabdar@Sun.COM  *   void
1168*7917SReza.Sabdar@Sun.COM  */
1169*7917SReza.Sabdar@Sun.COM /*ARGSUSED*/
1170*7917SReza.Sabdar@Sun.COM static void
1171*7917SReza.Sabdar@Sun.COM data_accept_connection_v3(void *cookie, int fd, ulong_t mode)
1172*7917SReza.Sabdar@Sun.COM {
1173*7917SReza.Sabdar@Sun.COM 	ndmpd_session_t *session = (ndmpd_session_t *)cookie;
1174*7917SReza.Sabdar@Sun.COM 	int from_len;
1175*7917SReza.Sabdar@Sun.COM 	struct sockaddr_in from;
1176*7917SReza.Sabdar@Sun.COM 	int flag = 1;
1177*7917SReza.Sabdar@Sun.COM 
1178*7917SReza.Sabdar@Sun.COM 	from_len = sizeof (from);
1179*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_sock = accept(fd, (struct sockaddr *)&from,
1180*7917SReza.Sabdar@Sun.COM 	    &from_len);
1181*7917SReza.Sabdar@Sun.COM 
1182*7917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "sock fd: %d",
1183*7917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_sock);
1184*7917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "sin: port %d addr %s",
1185*7917SReza.Sabdar@Sun.COM 	    ntohs(from.sin_port),
1186*7917SReza.Sabdar@Sun.COM 	    inet_ntoa(IN_ADDR(from.sin_addr.s_addr)));
1187*7917SReza.Sabdar@Sun.COM 
1188*7917SReza.Sabdar@Sun.COM 	(void) ndmpd_remove_file_handler(session, fd);
1189*7917SReza.Sabdar@Sun.COM 	(void) close(session->ns_data.dd_listen_sock);
1190*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_listen_sock = -1;
1191*7917SReza.Sabdar@Sun.COM 
1192*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_sock < 0) {
1193*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Accept error: %m");
1194*7917SReza.Sabdar@Sun.COM 		ndmpd_data_error(session, NDMP_DATA_HALT_CONNECT_ERROR);
1195*7917SReza.Sabdar@Sun.COM 		return;
1196*7917SReza.Sabdar@Sun.COM 	}
1197*7917SReza.Sabdar@Sun.COM 
1198*7917SReza.Sabdar@Sun.COM 	/*
1199*7917SReza.Sabdar@Sun.COM 	 * Save the peer address.
1200*7917SReza.Sabdar@Sun.COM 	 */
1201*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_data_addr.tcp_ip_v3 = from.sin_addr.s_addr;
1202*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_data_addr.tcp_port_v3 = ntohs(from.sin_port);
1203*7917SReza.Sabdar@Sun.COM 
1204*7917SReza.Sabdar@Sun.COM 	/*
1205*7917SReza.Sabdar@Sun.COM 	 * Set the parameter of the new socket.
1206*7917SReza.Sabdar@Sun.COM 	 */
1207*7917SReza.Sabdar@Sun.COM 	(void) setsockopt(session->ns_data.dd_sock, SOL_SOCKET, SO_KEEPALIVE,
1208*7917SReza.Sabdar@Sun.COM 	    &flag, sizeof (flag));
1209*7917SReza.Sabdar@Sun.COM 	ndmp_set_socket_nodelay(session->ns_data.dd_sock);
1210*7917SReza.Sabdar@Sun.COM 	if (ndmp_sbs > 0)
1211*7917SReza.Sabdar@Sun.COM 		ndmp_set_socket_snd_buf(session->ns_data.dd_sock,
1212*7917SReza.Sabdar@Sun.COM 		    ndmp_sbs * KILOBYTE);
1213*7917SReza.Sabdar@Sun.COM 	if (ndmp_rbs > 0)
1214*7917SReza.Sabdar@Sun.COM 		ndmp_set_socket_rcv_buf(session->ns_data.dd_sock,
1215*7917SReza.Sabdar@Sun.COM 		    ndmp_rbs * KILOBYTE);
1216*7917SReza.Sabdar@Sun.COM 
1217*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_state = NDMP_DATA_STATE_CONNECTED;
1218*7917SReza.Sabdar@Sun.COM }
1219*7917SReza.Sabdar@Sun.COM 
1220*7917SReza.Sabdar@Sun.COM 
1221*7917SReza.Sabdar@Sun.COM /*
1222*7917SReza.Sabdar@Sun.COM  * create_listen_socket_v3
1223*7917SReza.Sabdar@Sun.COM  *
1224*7917SReza.Sabdar@Sun.COM  * Creates the data sockets for listening for a remote mover/data
1225*7917SReza.Sabdar@Sun.COM  * incoming connections.
1226*7917SReza.Sabdar@Sun.COM  */
1227*7917SReza.Sabdar@Sun.COM static int
1228*7917SReza.Sabdar@Sun.COM create_listen_socket_v3(ndmpd_session_t *session, ulong_t *addr, ushort_t *port)
1229*7917SReza.Sabdar@Sun.COM {
1230*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_listen_sock = ndmp_create_socket(addr, port);
1231*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_listen_sock < 0)
1232*7917SReza.Sabdar@Sun.COM 		return (-1);
1233*7917SReza.Sabdar@Sun.COM 
1234*7917SReza.Sabdar@Sun.COM 	/*
1235*7917SReza.Sabdar@Sun.COM 	 * Add a file handler for the listen socket.
1236*7917SReza.Sabdar@Sun.COM 	 * ndmpd_select will call data_accept_connection when a
1237*7917SReza.Sabdar@Sun.COM 	 * connection is ready to be accepted.
1238*7917SReza.Sabdar@Sun.COM 	 */
1239*7917SReza.Sabdar@Sun.COM 	if (ndmpd_add_file_handler(session, (void*)session,
1240*7917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_listen_sock, NDMPD_SELECT_MODE_READ, HC_MOVER,
1241*7917SReza.Sabdar@Sun.COM 	    data_accept_connection_v3) < 0) {
1242*7917SReza.Sabdar@Sun.COM 		(void) close(session->ns_data.dd_listen_sock);
1243*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_listen_sock = -1;
1244*7917SReza.Sabdar@Sun.COM 		return (-1);
1245*7917SReza.Sabdar@Sun.COM 	}
1246*7917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "addr: %s:%d",
1247*7917SReza.Sabdar@Sun.COM 	    inet_ntoa(IN_ADDR(*addr)), ntohs(*port));
1248*7917SReza.Sabdar@Sun.COM 
1249*7917SReza.Sabdar@Sun.COM 	return (0);
1250*7917SReza.Sabdar@Sun.COM }
1251*7917SReza.Sabdar@Sun.COM 
1252*7917SReza.Sabdar@Sun.COM 
1253*7917SReza.Sabdar@Sun.COM /*
1254*7917SReza.Sabdar@Sun.COM  * data_connect_sock_v3
1255*7917SReza.Sabdar@Sun.COM  *
1256*7917SReza.Sabdar@Sun.COM  * Connect the data interface socket to the specified ip/port
1257*7917SReza.Sabdar@Sun.COM  *
1258*7917SReza.Sabdar@Sun.COM  * Parameters:
1259*7917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
1260*7917SReza.Sabdar@Sun.COM  *   addr    (input) - IP address
1261*7917SReza.Sabdar@Sun.COM  *   port    (input) - port number
1262*7917SReza.Sabdar@Sun.COM  *
1263*7917SReza.Sabdar@Sun.COM  * Returns:
1264*7917SReza.Sabdar@Sun.COM  *   NDMP_NO_ERR - backup successfully started.
1265*7917SReza.Sabdar@Sun.COM  *   otherwise - error code of backup start error.
1266*7917SReza.Sabdar@Sun.COM  */
1267*7917SReza.Sabdar@Sun.COM static ndmp_error
1268*7917SReza.Sabdar@Sun.COM data_connect_sock_v3(ndmpd_session_t *session, ulong_t addr, ushort_t port)
1269*7917SReza.Sabdar@Sun.COM {
1270*7917SReza.Sabdar@Sun.COM 	int sock;
1271*7917SReza.Sabdar@Sun.COM 
1272*7917SReza.Sabdar@Sun.COM 	sock = ndmp_connect_sock_v3(addr, port);
1273*7917SReza.Sabdar@Sun.COM 	if (sock < 0)
1274*7917SReza.Sabdar@Sun.COM 		return (NDMP_CONNECT_ERR);
1275*7917SReza.Sabdar@Sun.COM 
1276*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_sock = sock;
1277*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_TCP;
1278*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_data_addr.tcp_ip_v3 = ntohl(addr);
1279*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_data_addr.tcp_port_v3 = port;
1280*7917SReza.Sabdar@Sun.COM 
1281*7917SReza.Sabdar@Sun.COM 	return (NDMP_NO_ERR);
1282*7917SReza.Sabdar@Sun.COM }
1283*7917SReza.Sabdar@Sun.COM 
1284*7917SReza.Sabdar@Sun.COM 
1285*7917SReza.Sabdar@Sun.COM /*
1286*7917SReza.Sabdar@Sun.COM  * start_backup_v3
1287*7917SReza.Sabdar@Sun.COM  *
1288*7917SReza.Sabdar@Sun.COM  * Start the backup work
1289*7917SReza.Sabdar@Sun.COM  *
1290*7917SReza.Sabdar@Sun.COM  * Parameters:
1291*7917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
1292*7917SReza.Sabdar@Sun.COM  *   bu_type (input) - backup type.
1293*7917SReza.Sabdar@Sun.COM  *   env_val (input) - environment variable array.
1294*7917SReza.Sabdar@Sun.COM  *   env_len (input) - length of env_val.
1295*7917SReza.Sabdar@Sun.COM  *
1296*7917SReza.Sabdar@Sun.COM  * Returns:
1297*7917SReza.Sabdar@Sun.COM  *   NDMP_NO_ERR - backup successfully started.
1298*7917SReza.Sabdar@Sun.COM  *   otherwise - error code of backup start error.
1299*7917SReza.Sabdar@Sun.COM  */
1300*7917SReza.Sabdar@Sun.COM static ndmp_error
1301*7917SReza.Sabdar@Sun.COM start_backup_v3(ndmpd_session_t *session, char *bu_type, ndmp_pval *env_val,
1302*7917SReza.Sabdar@Sun.COM     ulong_t env_len)
1303*7917SReza.Sabdar@Sun.COM {
1304*7917SReza.Sabdar@Sun.COM 	int err;
1305*7917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
1306*7917SReza.Sabdar@Sun.COM 	ndmpd_module_params_t *params;
1307*7917SReza.Sabdar@Sun.COM 	ndmp_data_start_backup_reply_v3 reply;
1308*7917SReza.Sabdar@Sun.COM 
1309*7917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
1310*7917SReza.Sabdar@Sun.COM 
1311*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_CONNECTED) {
1312*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR,
1313*7917SReza.Sabdar@Sun.COM 		    "Can't start new backup in current state.");
1314*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR,
1315*7917SReza.Sabdar@Sun.COM 		    "Connection to the mover is not established.");
1316*7917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_STATE_ERR);
1317*7917SReza.Sabdar@Sun.COM 	}
1318*7917SReza.Sabdar@Sun.COM 
1319*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_LOCAL) {
1320*7917SReza.Sabdar@Sun.COM 		if (session->ns_tape.td_mode == NDMP_TAPE_READ_MODE) {
1321*7917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_ERR, "Write protected device.");
1322*7917SReza.Sabdar@Sun.COM 			return (NDMP_WRITE_PROTECT_ERR);
1323*7917SReza.Sabdar@Sun.COM 		}
1324*7917SReza.Sabdar@Sun.COM 	}
1325*7917SReza.Sabdar@Sun.COM 
1326*7917SReza.Sabdar@Sun.COM 	if (strcmp(bu_type, NDMP_DUMP_TYPE) != 0 &&
1327*7917SReza.Sabdar@Sun.COM 	    strcmp(bu_type, NDMP_TAR_TYPE) != 0) {
1328*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid backup type: %s.", bu_type);
1329*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Supported backup types are tar and dump.");
1330*7917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
1331*7917SReza.Sabdar@Sun.COM 	}
1332*7917SReza.Sabdar@Sun.COM 
1333*7917SReza.Sabdar@Sun.COM 	err = ndmpd_save_env(session, env_val, env_len);
1334*7917SReza.Sabdar@Sun.COM 	if (err != NDMP_NO_ERR)
1335*7917SReza.Sabdar@Sun.COM 		return (err);
1336*7917SReza.Sabdar@Sun.COM 
1337*7917SReza.Sabdar@Sun.COM 	nlp = ndmp_get_nlp(session);
1338*7917SReza.Sabdar@Sun.COM 	NDMP_FREE(nlp->nlp_params);
1339*7917SReza.Sabdar@Sun.COM 	params = nlp->nlp_params = ndmp_malloc(sizeof (ndmpd_module_params_t));
1340*7917SReza.Sabdar@Sun.COM 	if (!params)
1341*7917SReza.Sabdar@Sun.COM 		return (NDMP_NO_MEM_ERR);
1342*7917SReza.Sabdar@Sun.COM 
1343*7917SReza.Sabdar@Sun.COM 	params->mp_daemon_cookie = (void *)session;
1344*7917SReza.Sabdar@Sun.COM 	params->mp_module_cookie = &session->ns_data.dd_module.dm_module_cookie;
1345*7917SReza.Sabdar@Sun.COM 	params->mp_protocol_version = session->ns_protocol_version;
1346*7917SReza.Sabdar@Sun.COM 	params->mp_operation = NDMP_DATA_OP_BACKUP;
1347*7917SReza.Sabdar@Sun.COM 	params->mp_get_env_func = ndmpd_api_get_env;
1348*7917SReza.Sabdar@Sun.COM 	params->mp_add_env_func = ndmpd_api_add_env;
1349*7917SReza.Sabdar@Sun.COM 	params->mp_set_env_func = ndmpd_api_set_env;
1350*7917SReza.Sabdar@Sun.COM 	params->mp_get_name_func = 0;
1351*7917SReza.Sabdar@Sun.COM 	params->mp_dispatch_func = ndmpd_api_dispatch;
1352*7917SReza.Sabdar@Sun.COM 	params->mp_done_func = ndmpd_api_done_v3;
1353*7917SReza.Sabdar@Sun.COM 	if (session->ns_protocol_version == NDMPV4)
1354*7917SReza.Sabdar@Sun.COM 		params->mp_log_func_v3 = ndmpd_api_log_v4;
1355*7917SReza.Sabdar@Sun.COM 	else
1356*7917SReza.Sabdar@Sun.COM 		params->mp_log_func_v3 = ndmpd_api_log_v3;
1357*7917SReza.Sabdar@Sun.COM 
1358*7917SReza.Sabdar@Sun.COM 	params->mp_add_file_handler_func = ndmpd_api_add_file_handler;
1359*7917SReza.Sabdar@Sun.COM 	params->mp_remove_file_handler_func = ndmpd_api_remove_file_handler;
1360*7917SReza.Sabdar@Sun.COM 	params->mp_write_func = ndmpd_api_write_v3;
1361*7917SReza.Sabdar@Sun.COM 	params->mp_read_func = 0;
1362*7917SReza.Sabdar@Sun.COM 	params->mp_file_recovered_func = 0;
1363*7917SReza.Sabdar@Sun.COM 	params->mp_stats = &session->ns_data.dd_module.dm_stats;
1364*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_module_cookie = 0;
1365*7917SReza.Sabdar@Sun.COM 
1366*7917SReza.Sabdar@Sun.COM 	if (strcmp(bu_type, NDMP_DUMP_TYPE) == 0) {
1367*7917SReza.Sabdar@Sun.COM 		NLP_SET(nlp, NLPF_DUMP);
1368*7917SReza.Sabdar@Sun.COM 		params->mp_file_history_path_func = 0;
1369*7917SReza.Sabdar@Sun.COM 		params->mp_file_history_dir_func =
1370*7917SReza.Sabdar@Sun.COM 		    ndmpd_api_file_history_dir_v3;
1371*7917SReza.Sabdar@Sun.COM 		params->mp_file_history_node_func =
1372*7917SReza.Sabdar@Sun.COM 		    ndmpd_api_file_history_node_v3;
1373*7917SReza.Sabdar@Sun.COM 	} else if (strcmp(bu_type, NDMP_TAR_TYPE) == 0) {
1374*7917SReza.Sabdar@Sun.COM 		NLP_SET(nlp, NLPF_TAR);
1375*7917SReza.Sabdar@Sun.COM 		params->mp_file_history_path_func =
1376*7917SReza.Sabdar@Sun.COM 		    ndmpd_api_file_history_file_v3;
1377*7917SReza.Sabdar@Sun.COM 		params->mp_file_history_dir_func = 0;
1378*7917SReza.Sabdar@Sun.COM 		params->mp_file_history_node_func = 0;
1379*7917SReza.Sabdar@Sun.COM 	} else {
1380*7917SReza.Sabdar@Sun.COM 		NLP_UNSET(nlp, NLPF_DUMP);
1381*7917SReza.Sabdar@Sun.COM 		NLP_UNSET(nlp, NLPF_TAR);
1382*7917SReza.Sabdar@Sun.COM 	}
1383*7917SReza.Sabdar@Sun.COM 
1384*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_start_func = ndmpd_tar_backup_starter_v3;
1385*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_abort_func = ndmpd_tar_backup_abort_v3;
1386*7917SReza.Sabdar@Sun.COM 
1387*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_bytes_remaining = 0;
1388*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_time_remaining  = 0;
1389*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_nlist_v3 = 0;
1390*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_nlist_len = 0;
1391*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_bytes_left_to_read = 0;
1392*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_position = 0;
1393*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_discard_length = 0;
1394*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_offset = 0;
1395*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_length = 0;
1396*7917SReza.Sabdar@Sun.COM 
1397*7917SReza.Sabdar@Sun.COM 	reply.error = ndmp_backup_get_params_v3(session, params);
1398*7917SReza.Sabdar@Sun.COM 	if (reply.error != NDMP_NO_ERR) {
1399*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "err: %d", err);
1400*7917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
1401*7917SReza.Sabdar@Sun.COM 		return (reply.error);
1402*7917SReza.Sabdar@Sun.COM 	}
1403*7917SReza.Sabdar@Sun.COM 
1404*7917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
1405*7917SReza.Sabdar@Sun.COM 	if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
1406*7917SReza.Sabdar@Sun.COM 	    &reply) < 0) {
1407*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Sending data_start_backup_v3 reply");
1408*7917SReza.Sabdar@Sun.COM 		return (NDMP_NO_ERR);
1409*7917SReza.Sabdar@Sun.COM 	}
1410*7917SReza.Sabdar@Sun.COM 
1411*7917SReza.Sabdar@Sun.COM 	NS_INC(nbk);
1412*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_state = NDMP_DATA_STATE_ACTIVE;
1413*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_operation = NDMP_DATA_OP_BACKUP;
1414*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_abort = FALSE;
1415*7917SReza.Sabdar@Sun.COM 
1416*7917SReza.Sabdar@Sun.COM 	/*
1417*7917SReza.Sabdar@Sun.COM 	 * perform the backup
1418*7917SReza.Sabdar@Sun.COM 	 *
1419*7917SReza.Sabdar@Sun.COM 	 * Cannot wait for the thread to exit as we are replying the
1420*7917SReza.Sabdar@Sun.COM 	 * client request here.
1421*7917SReza.Sabdar@Sun.COM 	 */
1422*7917SReza.Sabdar@Sun.COM 	err = pthread_create(NULL, NULL,
1423*7917SReza.Sabdar@Sun.COM 	    (funct_t)session->ns_data.dd_module.dm_start_func,
1424*7917SReza.Sabdar@Sun.COM 	    params);
1425*7917SReza.Sabdar@Sun.COM 	if (err != 0) {
1426*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Can't start backup session.");
1427*7917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
1428*7917SReza.Sabdar@Sun.COM 	}
1429*7917SReza.Sabdar@Sun.COM 
1430*7917SReza.Sabdar@Sun.COM 	return (NDMP_NO_ERR);
1431*7917SReza.Sabdar@Sun.COM }
1432*7917SReza.Sabdar@Sun.COM 
1433*7917SReza.Sabdar@Sun.COM 
1434*7917SReza.Sabdar@Sun.COM /*
1435*7917SReza.Sabdar@Sun.COM  * start_recover_v3
1436*7917SReza.Sabdar@Sun.COM  *
1437*7917SReza.Sabdar@Sun.COM  * Start the restore work
1438*7917SReza.Sabdar@Sun.COM  *
1439*7917SReza.Sabdar@Sun.COM  * Parameters:
1440*7917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
1441*7917SReza.Sabdar@Sun.COM  *   bu_type   (input) - backup type.
1442*7917SReza.Sabdar@Sun.COM  *   env_val   (input) - environment variable array.
1443*7917SReza.Sabdar@Sun.COM  *   env_len   (input) - length of env_val.
1444*7917SReza.Sabdar@Sun.COM  *
1445*7917SReza.Sabdar@Sun.COM  * Returns:
1446*7917SReza.Sabdar@Sun.COM  *   NDMP_NO_ERR - recover successfully started.
1447*7917SReza.Sabdar@Sun.COM  *   otherwise   - error code of recover start error.
1448*7917SReza.Sabdar@Sun.COM  */
1449*7917SReza.Sabdar@Sun.COM static ndmp_error
1450*7917SReza.Sabdar@Sun.COM start_recover_v3(ndmpd_session_t *session, char *bu_type, ndmp_pval *env_val,
1451*7917SReza.Sabdar@Sun.COM     ulong_t env_len, ndmp_name_v3 *nlist_val, ulong_t nlist_len)
1452*7917SReza.Sabdar@Sun.COM {
1453*7917SReza.Sabdar@Sun.COM 	ndmp_data_start_recover_reply_v3 reply;
1454*7917SReza.Sabdar@Sun.COM 	ndmpd_module_params_t *params;
1455*7917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
1456*7917SReza.Sabdar@Sun.COM 	int err;
1457*7917SReza.Sabdar@Sun.COM 
1458*7917SReza.Sabdar@Sun.COM 	(void) memset((void*)&reply, 0, sizeof (reply));
1459*7917SReza.Sabdar@Sun.COM 
1460*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_CONNECTED) {
1461*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Can't start new recover in current state.");
1462*7917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_STATE_ERR);
1463*7917SReza.Sabdar@Sun.COM 	}
1464*7917SReza.Sabdar@Sun.COM 	if (strcmp(bu_type, NDMP_DUMP_TYPE) != 0 &&
1465*7917SReza.Sabdar@Sun.COM 	    strcmp(bu_type, NDMP_TAR_TYPE) != 0) {
1466*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid backup type: %s.", bu_type);
1467*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Supported backup types are tar and dump.");
1468*7917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
1469*7917SReza.Sabdar@Sun.COM 	}
1470*7917SReza.Sabdar@Sun.COM 
1471*7917SReza.Sabdar@Sun.COM 	nlp = ndmp_get_nlp(session);
1472*7917SReza.Sabdar@Sun.COM 	NDMP_FREE(nlp->nlp_params);
1473*7917SReza.Sabdar@Sun.COM 	params = nlp->nlp_params = ndmp_malloc(sizeof (ndmpd_module_params_t));
1474*7917SReza.Sabdar@Sun.COM 	if (!params) {
1475*7917SReza.Sabdar@Sun.COM 		return (NDMP_NO_MEM_ERR);
1476*7917SReza.Sabdar@Sun.COM 	}
1477*7917SReza.Sabdar@Sun.COM 
1478*7917SReza.Sabdar@Sun.COM 	reply.error = ndmpd_save_env(session, env_val, env_len);
1479*7917SReza.Sabdar@Sun.COM 	if (reply.error != NDMP_NO_ERR) {
1480*7917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
1481*7917SReza.Sabdar@Sun.COM 		return (NDMP_NO_MEM_ERR);
1482*7917SReza.Sabdar@Sun.COM 	}
1483*7917SReza.Sabdar@Sun.COM 
1484*7917SReza.Sabdar@Sun.COM 	reply.error = ndmpd_save_nlist_v3(session, nlist_val, nlist_len);
1485*7917SReza.Sabdar@Sun.COM 	if (reply.error != NDMP_NO_ERR) {
1486*7917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
1487*7917SReza.Sabdar@Sun.COM 		return (NDMP_NO_MEM_ERR);
1488*7917SReza.Sabdar@Sun.COM 	}
1489*7917SReza.Sabdar@Sun.COM 
1490*7917SReza.Sabdar@Sun.COM 	/*
1491*7917SReza.Sabdar@Sun.COM 	 * Setup restore parameters.
1492*7917SReza.Sabdar@Sun.COM 	 */
1493*7917SReza.Sabdar@Sun.COM 	params->mp_daemon_cookie = (void *)session;
1494*7917SReza.Sabdar@Sun.COM 	params->mp_module_cookie = &session->ns_data.dd_module.dm_module_cookie;
1495*7917SReza.Sabdar@Sun.COM 	params->mp_protocol_version = session->ns_protocol_version;
1496*7917SReza.Sabdar@Sun.COM 	params->mp_operation = NDMP_DATA_OP_RECOVER;
1497*7917SReza.Sabdar@Sun.COM 	params->mp_get_env_func = ndmpd_api_get_env;
1498*7917SReza.Sabdar@Sun.COM 	params->mp_add_env_func = ndmpd_api_add_env;
1499*7917SReza.Sabdar@Sun.COM 	params->mp_set_env_func = ndmpd_api_set_env;
1500*7917SReza.Sabdar@Sun.COM 	params->mp_get_name_func = ndmpd_api_get_name_v3;
1501*7917SReza.Sabdar@Sun.COM 	params->mp_dispatch_func = ndmpd_api_dispatch;
1502*7917SReza.Sabdar@Sun.COM 	params->mp_done_func = ndmpd_api_done_v3;
1503*7917SReza.Sabdar@Sun.COM 	if (session->ns_protocol_version == NDMPV4) {
1504*7917SReza.Sabdar@Sun.COM 		params->mp_log_func_v3 = ndmpd_api_log_v4;
1505*7917SReza.Sabdar@Sun.COM 		params->mp_file_recovered_func = ndmpd_api_file_recovered_v4;
1506*7917SReza.Sabdar@Sun.COM 	} else {
1507*7917SReza.Sabdar@Sun.COM 		params->mp_log_func_v3 = ndmpd_api_log_v3;
1508*7917SReza.Sabdar@Sun.COM 		params->mp_file_recovered_func = ndmpd_api_file_recovered_v3;
1509*7917SReza.Sabdar@Sun.COM 	}
1510*7917SReza.Sabdar@Sun.COM 
1511*7917SReza.Sabdar@Sun.COM 	params->mp_add_file_handler_func = ndmpd_api_add_file_handler;
1512*7917SReza.Sabdar@Sun.COM 	params->mp_remove_file_handler_func = ndmpd_api_remove_file_handler;
1513*7917SReza.Sabdar@Sun.COM 	params->mp_write_func = 0;
1514*7917SReza.Sabdar@Sun.COM 	params->mp_file_history_path_func = 0;
1515*7917SReza.Sabdar@Sun.COM 	params->mp_file_history_dir_func = 0;
1516*7917SReza.Sabdar@Sun.COM 	params->mp_file_history_node_func = 0;
1517*7917SReza.Sabdar@Sun.COM 	params->mp_read_func = ndmpd_api_read_v3;
1518*7917SReza.Sabdar@Sun.COM 	params->mp_seek_func = ndmpd_api_seek_v3;
1519*7917SReza.Sabdar@Sun.COM 	params->mp_stats = &session->ns_data.dd_module.dm_stats;
1520*7917SReza.Sabdar@Sun.COM 
1521*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_module_cookie = 0;
1522*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_start_func = ndmpd_tar_restore_starter_v3;
1523*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_abort_func = ndmpd_tar_restore_abort_v3;
1524*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_bytes_remaining = 0;
1525*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_time_remaining = 0;
1526*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_bytes_left_to_read = 0;
1527*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_position = 0;
1528*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_discard_length = 0;
1529*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_offset = 0;
1530*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_length = 0;
1531*7917SReza.Sabdar@Sun.COM 
1532*7917SReza.Sabdar@Sun.COM 	err = ndmp_restore_get_params_v3(session, params);
1533*7917SReza.Sabdar@Sun.COM 	if (err != NDMP_NO_ERR) {
1534*7917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
1535*7917SReza.Sabdar@Sun.COM 		return (err);
1536*7917SReza.Sabdar@Sun.COM 	}
1537*7917SReza.Sabdar@Sun.COM 
1538*7917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
1539*7917SReza.Sabdar@Sun.COM 	if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
1540*7917SReza.Sabdar@Sun.COM 	    &reply) < 0) {
1541*7917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
1542*7917SReza.Sabdar@Sun.COM 		ndmpd_free_nlist_v3(session);
1543*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
1544*7917SReza.Sabdar@Sun.COM 		    "Error sending ndmp_data_start_recover_reply");
1545*7917SReza.Sabdar@Sun.COM 		ndmpd_data_error(session, NDMP_DATA_HALT_CONNECT_ERROR);
1546*7917SReza.Sabdar@Sun.COM 		return (NDMP_NO_ERR);
1547*7917SReza.Sabdar@Sun.COM 	}
1548*7917SReza.Sabdar@Sun.COM 
1549*7917SReza.Sabdar@Sun.COM 	NS_INC(nrs);
1550*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_state = NDMP_DATA_STATE_ACTIVE;
1551*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_operation = NDMP_DATA_OP_RECOVER;
1552*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_abort = FALSE;
1553*7917SReza.Sabdar@Sun.COM 
1554*7917SReza.Sabdar@Sun.COM 	/*
1555*7917SReza.Sabdar@Sun.COM 	 * perform the restore
1556*7917SReza.Sabdar@Sun.COM 	 *
1557*7917SReza.Sabdar@Sun.COM 	 * Cannot wait for the thread to exit as we are replying to the
1558*7917SReza.Sabdar@Sun.COM 	 * client request here.
1559*7917SReza.Sabdar@Sun.COM 	 */
1560*7917SReza.Sabdar@Sun.COM 	err = pthread_create(NULL, NULL,
1561*7917SReza.Sabdar@Sun.COM 	    (funct_t)session->ns_data.dd_module.dm_start_func,
1562*7917SReza.Sabdar@Sun.COM 	    params);
1563*7917SReza.Sabdar@Sun.COM 
1564*7917SReza.Sabdar@Sun.COM 	if (err != 0) {
1565*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Can't start recover session.");
1566*7917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
1567*7917SReza.Sabdar@Sun.COM 	}
1568*7917SReza.Sabdar@Sun.COM 	return (NDMP_NO_ERR);
1569*7917SReza.Sabdar@Sun.COM }
1570*7917SReza.Sabdar@Sun.COM 
1571*7917SReza.Sabdar@Sun.COM 
1572*7917SReza.Sabdar@Sun.COM /*
1573*7917SReza.Sabdar@Sun.COM  * discard_data_v3
1574*7917SReza.Sabdar@Sun.COM  *
1575*7917SReza.Sabdar@Sun.COM  * Read and discard data from the data connection.
1576*7917SReza.Sabdar@Sun.COM  * Called when a module has called ndmpd_seek() prior to
1577*7917SReza.Sabdar@Sun.COM  * reading all of the data from the previous seek.
1578*7917SReza.Sabdar@Sun.COM  *
1579*7917SReza.Sabdar@Sun.COM  * Parameters:
1580*7917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
1581*7917SReza.Sabdar@Sun.COM  *
1582*7917SReza.Sabdar@Sun.COM  * Returns:
1583*7917SReza.Sabdar@Sun.COM  *   number of bytes read and discarded.
1584*7917SReza.Sabdar@Sun.COM  *  -1 - error.
1585*7917SReza.Sabdar@Sun.COM  */
1586*7917SReza.Sabdar@Sun.COM static int
1587*7917SReza.Sabdar@Sun.COM discard_data_v3(ndmpd_session_t *session, ulong_t length)
1588*7917SReza.Sabdar@Sun.COM {
1589*7917SReza.Sabdar@Sun.COM 	static char buf[MAX_RECORD_SIZE];
1590*7917SReza.Sabdar@Sun.COM 	int n, toread;
1591*7917SReza.Sabdar@Sun.COM 
1592*7917SReza.Sabdar@Sun.COM 	toread = (length < MAX_RECORD_SIZE) ? length :
1593*7917SReza.Sabdar@Sun.COM 	    MAX_RECORD_SIZE;
1594*7917SReza.Sabdar@Sun.COM 
1595*7917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "discard data, length = %u", length);
1596*7917SReza.Sabdar@Sun.COM 
1597*7917SReza.Sabdar@Sun.COM 	/* Read and discard the data. */
1598*7917SReza.Sabdar@Sun.COM 	n = read(session->ns_data.dd_sock, buf, toread);
1599*7917SReza.Sabdar@Sun.COM 	if (n < 0) {
1600*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Socket read error: %m.");
1601*7917SReza.Sabdar@Sun.COM 		n = -1;
1602*7917SReza.Sabdar@Sun.COM 	}
1603*7917SReza.Sabdar@Sun.COM 
1604*7917SReza.Sabdar@Sun.COM 	return (n);
1605*7917SReza.Sabdar@Sun.COM }
1606*7917SReza.Sabdar@Sun.COM 
1607*7917SReza.Sabdar@Sun.COM 
1608*7917SReza.Sabdar@Sun.COM /*
1609*7917SReza.Sabdar@Sun.COM  * ndmpd_remote_read_v3
1610*7917SReza.Sabdar@Sun.COM  *
1611*7917SReza.Sabdar@Sun.COM  * Reads data from the remote mover.
1612*7917SReza.Sabdar@Sun.COM  *
1613*7917SReza.Sabdar@Sun.COM  * Parameters:
1614*7917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
1615*7917SReza.Sabdar@Sun.COM  *   data    (input) - data to be written.
1616*7917SReza.Sabdar@Sun.COM  *   length  (input) - data length.
1617*7917SReza.Sabdar@Sun.COM  *
1618*7917SReza.Sabdar@Sun.COM  * Returns:
1619*7917SReza.Sabdar@Sun.COM  *   0 - data successfully read.
1620*7917SReza.Sabdar@Sun.COM  *  -1 - error.
1621*7917SReza.Sabdar@Sun.COM  */
1622*7917SReza.Sabdar@Sun.COM int
1623*7917SReza.Sabdar@Sun.COM ndmpd_remote_read_v3(ndmpd_session_t *session, char *data, ulong_t length)
1624*7917SReza.Sabdar@Sun.COM {
1625*7917SReza.Sabdar@Sun.COM 	ulong_t count;
1626*7917SReza.Sabdar@Sun.COM 	ulong_t len;
1627*7917SReza.Sabdar@Sun.COM 	ssize_t n;
1628*7917SReza.Sabdar@Sun.COM 	ndmp_notify_data_read_request request;
1629*7917SReza.Sabdar@Sun.COM 	tlm_job_stats_t *jstat;
1630*7917SReza.Sabdar@Sun.COM 	longlong_t fsize;
1631*7917SReza.Sabdar@Sun.COM 
1632*7917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "ns_data.dd_xx: [%llu, %llu, %llu, %llu, %llu]",
1633*7917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_bytes_left_to_read,
1634*7917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_read_offset,
1635*7917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_read_length,
1636*7917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_position,
1637*7917SReza.Sabdar@Sun.COM 	    session->ns_data.dd_discard_length);
1638*7917SReza.Sabdar@Sun.COM 
1639*7917SReza.Sabdar@Sun.COM 	count = 0;
1640*7917SReza.Sabdar@Sun.COM 	while (count < length) {
1641*7917SReza.Sabdar@Sun.COM 		len = length - count;
1642*7917SReza.Sabdar@Sun.COM 
1643*7917SReza.Sabdar@Sun.COM 		/*
1644*7917SReza.Sabdar@Sun.COM 		 * If the end of the seek window has been reached then
1645*7917SReza.Sabdar@Sun.COM 		 * send an ndmp_read request to the client.
1646*7917SReza.Sabdar@Sun.COM 		 * The NDMP client will then send a mover_data_read request to
1647*7917SReza.Sabdar@Sun.COM 		 * the remote mover and the mover will send more data.
1648*7917SReza.Sabdar@Sun.COM 		 * This condition can occur if the module attempts to read past
1649*7917SReza.Sabdar@Sun.COM 		 * a seek window set via a prior call to ndmpd_seek() or
1650*7917SReza.Sabdar@Sun.COM 		 * the module has not issued a seek. If no seek was issued then
1651*7917SReza.Sabdar@Sun.COM 		 * pretend that a seek was issued to read the entire tape.
1652*7917SReza.Sabdar@Sun.COM 		 */
1653*7917SReza.Sabdar@Sun.COM 		if (session->ns_data.dd_bytes_left_to_read == 0) {
1654*7917SReza.Sabdar@Sun.COM 			/* ndmpd_seek() never called? */
1655*7917SReza.Sabdar@Sun.COM 			if (session->ns_data.dd_read_length == 0) {
1656*7917SReza.Sabdar@Sun.COM 				session->ns_data.dd_bytes_left_to_read = ~0LL;
1657*7917SReza.Sabdar@Sun.COM 				session->ns_data.dd_read_offset = 0LL;
1658*7917SReza.Sabdar@Sun.COM 				session->ns_data.dd_read_length = ~0LL;
1659*7917SReza.Sabdar@Sun.COM 			} else {
1660*7917SReza.Sabdar@Sun.COM 				/*
1661*7917SReza.Sabdar@Sun.COM 				 * While restoring a file, restoreFile()
1662*7917SReza.Sabdar@Sun.COM 				 * records the number of bytes still need to
1663*7917SReza.Sabdar@Sun.COM 				 * be restored.  We use this as a guidance
1664*7917SReza.Sabdar@Sun.COM 				 * when asking for data from the tape.
1665*7917SReza.Sabdar@Sun.COM 				 */
1666*7917SReza.Sabdar@Sun.COM 				jstat = session->ns_ndmp_lbr_params->nlp_jstat;
1667*7917SReza.Sabdar@Sun.COM 				fsize = jstat->js_bytes_in_file;
1668*7917SReza.Sabdar@Sun.COM 
1669*7917SReza.Sabdar@Sun.COM 				NDMP_LOG(LOG_DEBUG, "bytes_left [%llu / %u]",
1670*7917SReza.Sabdar@Sun.COM 				    fsize, len);
1671*7917SReza.Sabdar@Sun.COM 
1672*7917SReza.Sabdar@Sun.COM 				/*
1673*7917SReza.Sabdar@Sun.COM 				 * Fall back to the old way if fsize if too
1674*7917SReza.Sabdar@Sun.COM 				 * small.
1675*7917SReza.Sabdar@Sun.COM 				 */
1676*7917SReza.Sabdar@Sun.COM 				if (fsize < len)
1677*7917SReza.Sabdar@Sun.COM 					fsize = len;
1678*7917SReza.Sabdar@Sun.COM 
1679*7917SReza.Sabdar@Sun.COM 				session->ns_data.dd_bytes_left_to_read = fsize;
1680*7917SReza.Sabdar@Sun.COM 				session->ns_data.dd_read_offset =
1681*7917SReza.Sabdar@Sun.COM 				    session->ns_data.dd_position;
1682*7917SReza.Sabdar@Sun.COM 				session->ns_data.dd_read_length = fsize;
1683*7917SReza.Sabdar@Sun.COM 			}
1684*7917SReza.Sabdar@Sun.COM 
1685*7917SReza.Sabdar@Sun.COM 			request.offset =
1686*7917SReza.Sabdar@Sun.COM 			    long_long_to_quad(session->ns_data.dd_read_offset);
1687*7917SReza.Sabdar@Sun.COM 			request.length =
1688*7917SReza.Sabdar@Sun.COM 			    long_long_to_quad(session->ns_data.dd_read_length);
1689*7917SReza.Sabdar@Sun.COM 
1690*7917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG, "to NOTIFY_DATA_READ [%llu, %llu]",
1691*7917SReza.Sabdar@Sun.COM 			    session->ns_data.dd_read_offset,
1692*7917SReza.Sabdar@Sun.COM 			    session->ns_data.dd_read_length);
1693*7917SReza.Sabdar@Sun.COM 
1694*7917SReza.Sabdar@Sun.COM 			if (ndmp_send_request(session->ns_connection,
1695*7917SReza.Sabdar@Sun.COM 			    NDMP_NOTIFY_DATA_READ, NDMP_NO_ERR,
1696*7917SReza.Sabdar@Sun.COM 			    &request, 0) < 0) {
1697*7917SReza.Sabdar@Sun.COM 				NDMP_LOG(LOG_DEBUG,
1698*7917SReza.Sabdar@Sun.COM 				    "Sending notify_data_read request");
1699*7917SReza.Sabdar@Sun.COM 				return (-1);
1700*7917SReza.Sabdar@Sun.COM 			}
1701*7917SReza.Sabdar@Sun.COM 		}
1702*7917SReza.Sabdar@Sun.COM 
1703*7917SReza.Sabdar@Sun.COM 		/*
1704*7917SReza.Sabdar@Sun.COM 		 * If the module called ndmpd_seek() prior to reading all of the
1705*7917SReza.Sabdar@Sun.COM 		 * data that the remote mover was requested to send, then the
1706*7917SReza.Sabdar@Sun.COM 		 * excess data from the seek has to be discarded.
1707*7917SReza.Sabdar@Sun.COM 		 */
1708*7917SReza.Sabdar@Sun.COM 		if (session->ns_data.dd_discard_length != 0) {
1709*7917SReza.Sabdar@Sun.COM 			n = discard_data_v3(session,
1710*7917SReza.Sabdar@Sun.COM 			    (ulong_t)session->ns_data.dd_discard_length);
1711*7917SReza.Sabdar@Sun.COM 			if (n < 0)
1712*7917SReza.Sabdar@Sun.COM 				return (-1);
1713*7917SReza.Sabdar@Sun.COM 
1714*7917SReza.Sabdar@Sun.COM 			session->ns_data.dd_discard_length -= n;
1715*7917SReza.Sabdar@Sun.COM 			continue;
1716*7917SReza.Sabdar@Sun.COM 		}
1717*7917SReza.Sabdar@Sun.COM 
1718*7917SReza.Sabdar@Sun.COM 		/*
1719*7917SReza.Sabdar@Sun.COM 		 * Don't attempt to read more data than the remote is sending.
1720*7917SReza.Sabdar@Sun.COM 		 */
1721*7917SReza.Sabdar@Sun.COM 		if (len > session->ns_data.dd_bytes_left_to_read)
1722*7917SReza.Sabdar@Sun.COM 			len = session->ns_data.dd_bytes_left_to_read;
1723*7917SReza.Sabdar@Sun.COM 
1724*7917SReza.Sabdar@Sun.COM 		if ((n = read(session->ns_data.dd_sock, &data[count],
1725*7917SReza.Sabdar@Sun.COM 		    len)) < 0) {
1726*7917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_ERR, "Socket read error: %m.");
1727*7917SReza.Sabdar@Sun.COM 			return (-1);
1728*7917SReza.Sabdar@Sun.COM 		}
1729*7917SReza.Sabdar@Sun.COM 
1730*7917SReza.Sabdar@Sun.COM 		/* read returns 0 if the connection was closed */
1731*7917SReza.Sabdar@Sun.COM 		if (n == 0) {
1732*7917SReza.Sabdar@Sun.COM 			NDMP_LOG(LOG_DEBUG, "n 0 errno %d",
1733*7917SReza.Sabdar@Sun.COM 			    errno);
1734*7917SReza.Sabdar@Sun.COM 			return (-1);
1735*7917SReza.Sabdar@Sun.COM 		}
1736*7917SReza.Sabdar@Sun.COM 
1737*7917SReza.Sabdar@Sun.COM 		count += n;
1738*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_bytes_left_to_read -= n;
1739*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_position += n;
1740*7917SReza.Sabdar@Sun.COM 	}
1741*7917SReza.Sabdar@Sun.COM 
1742*7917SReza.Sabdar@Sun.COM 	return (0);
1743*7917SReza.Sabdar@Sun.COM }
1744*7917SReza.Sabdar@Sun.COM 
1745*7917SReza.Sabdar@Sun.COM 
1746*7917SReza.Sabdar@Sun.COM /*
1747*7917SReza.Sabdar@Sun.COM  * nlp_release_job_stat
1748*7917SReza.Sabdar@Sun.COM  *
1749*7917SReza.Sabdar@Sun.COM  * Unreference the job statistics
1750*7917SReza.Sabdar@Sun.COM  *
1751*7917SReza.Sabdar@Sun.COM  * Parameters:
1752*7917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
1753*7917SReza.Sabdar@Sun.COM  *
1754*7917SReza.Sabdar@Sun.COM  * Returns:
1755*7917SReza.Sabdar@Sun.COM  *   void
1756*7917SReza.Sabdar@Sun.COM  */
1757*7917SReza.Sabdar@Sun.COM static void
1758*7917SReza.Sabdar@Sun.COM nlp_release_job_stat(ndmpd_session_t *session)
1759*7917SReza.Sabdar@Sun.COM {
1760*7917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
1761*7917SReza.Sabdar@Sun.COM 
1762*7917SReza.Sabdar@Sun.COM 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
1763*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
1764*7917SReza.Sabdar@Sun.COM 		return;
1765*7917SReza.Sabdar@Sun.COM 	}
1766*7917SReza.Sabdar@Sun.COM 	if (nlp->nlp_jstat != NULL) {
1767*7917SReza.Sabdar@Sun.COM 		nlp->nlp_bytes_total =
1768*7917SReza.Sabdar@Sun.COM 		    (u_longlong_t)nlp->nlp_jstat->js_bytes_total;
1769*7917SReza.Sabdar@Sun.COM 		tlm_un_ref_job_stats(nlp->nlp_jstat->js_job_name);
1770*7917SReza.Sabdar@Sun.COM 		nlp->nlp_jstat = NULL;
1771*7917SReza.Sabdar@Sun.COM 	} else
1772*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "JSTAT == NULL");
1773*7917SReza.Sabdar@Sun.COM }
1774*7917SReza.Sabdar@Sun.COM 
1775*7917SReza.Sabdar@Sun.COM 
1776*7917SReza.Sabdar@Sun.COM /* *** ndmpd global internal functions *********************************** */
1777*7917SReza.Sabdar@Sun.COM 
1778*7917SReza.Sabdar@Sun.COM /*
1779*7917SReza.Sabdar@Sun.COM  * ndmpd_data_init
1780*7917SReza.Sabdar@Sun.COM  *
1781*7917SReza.Sabdar@Sun.COM  * Initializes data specific session variables.
1782*7917SReza.Sabdar@Sun.COM  *
1783*7917SReza.Sabdar@Sun.COM  * Parameters:
1784*7917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
1785*7917SReza.Sabdar@Sun.COM  *
1786*7917SReza.Sabdar@Sun.COM  * Returns:
1787*7917SReza.Sabdar@Sun.COM  *   void
1788*7917SReza.Sabdar@Sun.COM  */
1789*7917SReza.Sabdar@Sun.COM int
1790*7917SReza.Sabdar@Sun.COM ndmpd_data_init(ndmpd_session_t *session)
1791*7917SReza.Sabdar@Sun.COM {
1792*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_operation = NDMP_DATA_OP_NOACTION;
1793*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_state = NDMP_DATA_STATE_IDLE;
1794*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_halt_reason = NDMP_DATA_HALT_NA;
1795*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_abort = FALSE;
1796*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_env = 0;
1797*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_env_len = 0;
1798*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_nlist = 0;
1799*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_nlist_len = 0;
1800*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_mover.addr_type = NDMP_ADDR_LOCAL;
1801*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_sock = -1;
1802*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_offset = 0;
1803*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_length = 0;
1804*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_bytes_remaining = 0;
1805*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_time_remaining = 0;
1806*7917SReza.Sabdar@Sun.COM 	/*
1807*7917SReza.Sabdar@Sun.COM 	 * NDMP V3
1808*7917SReza.Sabdar@Sun.COM 	 */
1809*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_state = NDMP_DATA_STATE_IDLE;
1810*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_nlist_v3 = 0;
1811*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_data_addr.addr_type = NDMP_ADDR_LOCAL;
1812*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_listen_sock = -1;
1813*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_bytes_left_to_read = 0LL;
1814*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_position = 0LL;
1815*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_discard_length = 0LL;
1816*7917SReza.Sabdar@Sun.COM 	return (0);
1817*7917SReza.Sabdar@Sun.COM }
1818*7917SReza.Sabdar@Sun.COM 
1819*7917SReza.Sabdar@Sun.COM 
1820*7917SReza.Sabdar@Sun.COM 
1821*7917SReza.Sabdar@Sun.COM /*
1822*7917SReza.Sabdar@Sun.COM  * ndmpd_data_cleanup
1823*7917SReza.Sabdar@Sun.COM  *
1824*7917SReza.Sabdar@Sun.COM  * Releases resources allocated during a data operation.
1825*7917SReza.Sabdar@Sun.COM  *
1826*7917SReza.Sabdar@Sun.COM  * Parameters:
1827*7917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
1828*7917SReza.Sabdar@Sun.COM  *
1829*7917SReza.Sabdar@Sun.COM  * Returns:
1830*7917SReza.Sabdar@Sun.COM  *   void
1831*7917SReza.Sabdar@Sun.COM  */
1832*7917SReza.Sabdar@Sun.COM void
1833*7917SReza.Sabdar@Sun.COM ndmpd_data_cleanup(ndmpd_session_t *session)
1834*7917SReza.Sabdar@Sun.COM {
1835*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_listen_sock != -1) {
1836*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "data.listen_sock: %d",
1837*7917SReza.Sabdar@Sun.COM 		    session->ns_data.dd_listen_sock);
1838*7917SReza.Sabdar@Sun.COM 		(void) ndmpd_remove_file_handler(session,
1839*7917SReza.Sabdar@Sun.COM 		    session->ns_data.dd_listen_sock);
1840*7917SReza.Sabdar@Sun.COM 		(void) close(session->ns_data.dd_listen_sock);
1841*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_listen_sock = -1;
1842*7917SReza.Sabdar@Sun.COM 	}
1843*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_sock != -1) {
1844*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "data.sock: %d",
1845*7917SReza.Sabdar@Sun.COM 		    session->ns_data.dd_sock);
1846*7917SReza.Sabdar@Sun.COM 
1847*7917SReza.Sabdar@Sun.COM 		/*
1848*7917SReza.Sabdar@Sun.COM 		 * ndmpcopy: we use the same socket for the mover,
1849*7917SReza.Sabdar@Sun.COM 		 * so expect to close when mover is done!
1850*7917SReza.Sabdar@Sun.COM 		 */
1851*7917SReza.Sabdar@Sun.COM 		if (session->ns_data.dd_sock != session->ns_mover.md_sock)
1852*7917SReza.Sabdar@Sun.COM 			(void) close(session->ns_data.dd_sock);
1853*7917SReza.Sabdar@Sun.COM 
1854*7917SReza.Sabdar@Sun.COM 		session->ns_data.dd_sock = -1;
1855*7917SReza.Sabdar@Sun.COM 	}
1856*7917SReza.Sabdar@Sun.COM 
1857*7917SReza.Sabdar@Sun.COM 	ndmpd_free_env(session);
1858*7917SReza.Sabdar@Sun.COM 	ndmpd_free_nlist(session);
1859*7917SReza.Sabdar@Sun.COM }
1860*7917SReza.Sabdar@Sun.COM 
1861*7917SReza.Sabdar@Sun.COM 
1862*7917SReza.Sabdar@Sun.COM /*
1863*7917SReza.Sabdar@Sun.COM  * ndmp_data_get_mover_mode
1864*7917SReza.Sabdar@Sun.COM  *
1865*7917SReza.Sabdar@Sun.COM  * Return the mover mode
1866*7917SReza.Sabdar@Sun.COM  *
1867*7917SReza.Sabdar@Sun.COM  * Parameters:
1868*7917SReza.Sabdar@Sun.COM  *   session (input) - session pointer.
1869*7917SReza.Sabdar@Sun.COM  *
1870*7917SReza.Sabdar@Sun.COM  * Returns:
1871*7917SReza.Sabdar@Sun.COM  *   remote - remote backup
1872*7917SReza.Sabdar@Sun.COM  *   local  - local backup
1873*7917SReza.Sabdar@Sun.COM  */
1874*7917SReza.Sabdar@Sun.COM char *
1875*7917SReza.Sabdar@Sun.COM ndmp_data_get_mover_mode(ndmpd_session_t *session)
1876*7917SReza.Sabdar@Sun.COM {
1877*7917SReza.Sabdar@Sun.COM 	char *rv;
1878*7917SReza.Sabdar@Sun.COM 
1879*7917SReza.Sabdar@Sun.COM 	switch (session->ns_protocol_version) {
1880*7917SReza.Sabdar@Sun.COM 	case NDMPV2:
1881*7917SReza.Sabdar@Sun.COM 		rv = ((session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP)
1882*7917SReza.Sabdar@Sun.COM 		    ? "remote" : "local");
1883*7917SReza.Sabdar@Sun.COM 		break;
1884*7917SReza.Sabdar@Sun.COM 	case NDMPV3:
1885*7917SReza.Sabdar@Sun.COM 		rv = ((session->ns_data.dd_data_addr.addr_type == NDMP_ADDR_TCP)
1886*7917SReza.Sabdar@Sun.COM 		    ? "remote" : "local");
1887*7917SReza.Sabdar@Sun.COM 		break;
1888*7917SReza.Sabdar@Sun.COM 	case NDMPV4:
1889*7917SReza.Sabdar@Sun.COM 		rv = ((session->ns_data.dd_data_addr.addr_type ==
1890*7917SReza.Sabdar@Sun.COM 		    NDMP_ADDR_TCP ||
1891*7917SReza.Sabdar@Sun.COM 		    (session->ns_data.dd_data_addr_v4.addr_type ==
1892*7917SReza.Sabdar@Sun.COM 		    NDMP_ADDR_TCP)) ? "remote" : "local");
1893*7917SReza.Sabdar@Sun.COM 		break;
1894*7917SReza.Sabdar@Sun.COM 	default:
1895*7917SReza.Sabdar@Sun.COM 		rv = "Uknonwn";
1896*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid protocol version %d.",
1897*7917SReza.Sabdar@Sun.COM 		    session->ns_protocol_version);
1898*7917SReza.Sabdar@Sun.COM 	}
1899*7917SReza.Sabdar@Sun.COM 
1900*7917SReza.Sabdar@Sun.COM 	return (rv);
1901*7917SReza.Sabdar@Sun.COM }
1902*7917SReza.Sabdar@Sun.COM 
1903*7917SReza.Sabdar@Sun.COM /* *** static functions ******************************************** */
1904*7917SReza.Sabdar@Sun.COM 
1905*7917SReza.Sabdar@Sun.COM /*
1906*7917SReza.Sabdar@Sun.COM  * start_backup
1907*7917SReza.Sabdar@Sun.COM  *
1908*7917SReza.Sabdar@Sun.COM  * Request handling code common to version 1 and
1909*7917SReza.Sabdar@Sun.COM  * version 2 data_start_backup request handlers.
1910*7917SReza.Sabdar@Sun.COM  *
1911*7917SReza.Sabdar@Sun.COM  * Parameters:
1912*7917SReza.Sabdar@Sun.COM  *   session   (input) - session pointer.
1913*7917SReza.Sabdar@Sun.COM  *   bu_type   (input) - backup type.
1914*7917SReza.Sabdar@Sun.COM  *   env_val   (input) - environment variable array.
1915*7917SReza.Sabdar@Sun.COM  *   env_len   (input) - length of env_val.
1916*7917SReza.Sabdar@Sun.COM  *
1917*7917SReza.Sabdar@Sun.COM  * Returns:
1918*7917SReza.Sabdar@Sun.COM  *   NDMP_NO_ERR - backup successfully started.
1919*7917SReza.Sabdar@Sun.COM  *   otherwise - error code of backup start error.
1920*7917SReza.Sabdar@Sun.COM  */
1921*7917SReza.Sabdar@Sun.COM static ndmp_error
1922*7917SReza.Sabdar@Sun.COM start_backup(ndmpd_session_t *session, char *bu_type, ndmp_pval *env_val,
1923*7917SReza.Sabdar@Sun.COM     ulong_t env_len)
1924*7917SReza.Sabdar@Sun.COM {
1925*7917SReza.Sabdar@Sun.COM 	ndmp_data_start_backup_reply reply;
1926*7917SReza.Sabdar@Sun.COM 	ndmpd_module_params_t *params;
1927*7917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
1928*7917SReza.Sabdar@Sun.COM 	int err;
1929*7917SReza.Sabdar@Sun.COM 
1930*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
1931*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Can't start new backup in current state.");
1932*7917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_STATE_ERR);
1933*7917SReza.Sabdar@Sun.COM 	}
1934*7917SReza.Sabdar@Sun.COM 	if (strcmp(bu_type, NDMP_DUMP_TYPE) != 0 &&
1935*7917SReza.Sabdar@Sun.COM 	    strcmp(bu_type, NDMP_TAR_TYPE) != 0) {
1936*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid backup type: %s.", bu_type);
1937*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Supported backup types are tar and dump.");
1938*7917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
1939*7917SReza.Sabdar@Sun.COM 	}
1940*7917SReza.Sabdar@Sun.COM 	if ((err = ndmpd_save_env(session, env_val, env_len)) != NDMP_NO_ERR)
1941*7917SReza.Sabdar@Sun.COM 		return (err);
1942*7917SReza.Sabdar@Sun.COM 
1943*7917SReza.Sabdar@Sun.COM 	nlp = ndmp_get_nlp(session);
1944*7917SReza.Sabdar@Sun.COM 	NDMP_FREE(nlp->nlp_params);
1945*7917SReza.Sabdar@Sun.COM 	params = nlp->nlp_params = ndmp_malloc(sizeof (ndmpd_module_params_t));
1946*7917SReza.Sabdar@Sun.COM 	if (params == NULL)
1947*7917SReza.Sabdar@Sun.COM 		return (NDMP_NO_MEM_ERR);
1948*7917SReza.Sabdar@Sun.COM 
1949*7917SReza.Sabdar@Sun.COM 	params->mp_daemon_cookie = (void *)session;
1950*7917SReza.Sabdar@Sun.COM 	params->mp_module_cookie = &session->ns_data.dd_module.dm_module_cookie;
1951*7917SReza.Sabdar@Sun.COM 	params->mp_protocol_version = session->ns_protocol_version;
1952*7917SReza.Sabdar@Sun.COM 	params->mp_operation = NDMP_DATA_OP_BACKUP;
1953*7917SReza.Sabdar@Sun.COM 	params->mp_get_env_func = ndmpd_api_get_env;
1954*7917SReza.Sabdar@Sun.COM 	params->mp_add_env_func = ndmpd_api_add_env;
1955*7917SReza.Sabdar@Sun.COM 	params->mp_get_name_func = ndmpd_api_get_name;
1956*7917SReza.Sabdar@Sun.COM 	params->mp_dispatch_func = ndmpd_api_dispatch;
1957*7917SReza.Sabdar@Sun.COM 	params->mp_done_func = ndmpd_api_done_v2;
1958*7917SReza.Sabdar@Sun.COM 	params->mp_log_func = ndmpd_api_log_v2;
1959*7917SReza.Sabdar@Sun.COM 	params->mp_add_file_handler_func = ndmpd_api_add_file_handler;
1960*7917SReza.Sabdar@Sun.COM 	params->mp_remove_file_handler_func = ndmpd_api_remove_file_handler;
1961*7917SReza.Sabdar@Sun.COM 	params->mp_write_func = ndmpd_api_write_v2;
1962*7917SReza.Sabdar@Sun.COM 	params->mp_read_func = 0;
1963*7917SReza.Sabdar@Sun.COM 	params->mp_file_recovered_func = 0;
1964*7917SReza.Sabdar@Sun.COM 	params->mp_stats = &session->ns_data.dd_module.dm_stats;
1965*7917SReza.Sabdar@Sun.COM 
1966*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_module_cookie = 0;
1967*7917SReza.Sabdar@Sun.COM 	if (strcmp(bu_type, NDMP_DUMP_TYPE) == 0) {
1968*7917SReza.Sabdar@Sun.COM 		NLP_SET(nlp, NLPF_DUMP);
1969*7917SReza.Sabdar@Sun.COM 		params->mp_file_history_path_func = 0;
1970*7917SReza.Sabdar@Sun.COM 		params->mp_file_history_dir_func =
1971*7917SReza.Sabdar@Sun.COM 		    ndmpd_api_file_history_dir_v2;
1972*7917SReza.Sabdar@Sun.COM 		params->mp_file_history_node_func =
1973*7917SReza.Sabdar@Sun.COM 		    ndmpd_api_file_history_node_v2;
1974*7917SReza.Sabdar@Sun.COM 	} else if (strcmp(bu_type, NDMP_TAR_TYPE) == 0) {
1975*7917SReza.Sabdar@Sun.COM 		/* backup type == NDMP_TAR_TYPE */
1976*7917SReza.Sabdar@Sun.COM 		NLP_SET(nlp, NLPF_TAR);
1977*7917SReza.Sabdar@Sun.COM 		params->mp_file_history_path_func =
1978*7917SReza.Sabdar@Sun.COM 		    ndmpd_api_file_history_path_v2;
1979*7917SReza.Sabdar@Sun.COM 		params->mp_file_history_dir_func = 0;
1980*7917SReza.Sabdar@Sun.COM 		params->mp_file_history_node_func = 0;
1981*7917SReza.Sabdar@Sun.COM 	} else {
1982*7917SReza.Sabdar@Sun.COM 		NLP_UNSET(nlp, NLPF_DUMP);
1983*7917SReza.Sabdar@Sun.COM 		NLP_UNSET(nlp, NLPF_TAR);
1984*7917SReza.Sabdar@Sun.COM 	}
1985*7917SReza.Sabdar@Sun.COM 
1986*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_start_func = ndmpd_tar_backup_starter;
1987*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_abort_func = ndmpd_tar_backup_abort;
1988*7917SReza.Sabdar@Sun.COM 
1989*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_bytes_remaining = 0;
1990*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_time_remaining = 0;
1991*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_nlist = 0;
1992*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_nlist_len = 0;
1993*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_offset = 0;
1994*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_length = 0;
1995*7917SReza.Sabdar@Sun.COM 
1996*7917SReza.Sabdar@Sun.COM 	if ((err = ndmp_backup_extract_params(session,
1997*7917SReza.Sabdar@Sun.COM 	    params)) != NDMP_NO_ERR) {
1998*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "err: %d", err);
1999*7917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
2000*7917SReza.Sabdar@Sun.COM 		return (err);
2001*7917SReza.Sabdar@Sun.COM 	}
2002*7917SReza.Sabdar@Sun.COM 
2003*7917SReza.Sabdar@Sun.COM 	err = ndmpd_mover_connect(session, NDMP_MOVER_MODE_READ);
2004*7917SReza.Sabdar@Sun.COM 	if (err != NDMP_NO_ERR) {
2005*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG,
2006*7917SReza.Sabdar@Sun.COM 		    "mover connect err: %d", err);
2007*7917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
2008*7917SReza.Sabdar@Sun.COM 		return (err);
2009*7917SReza.Sabdar@Sun.COM 	}
2010*7917SReza.Sabdar@Sun.COM 
2011*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_state = NDMP_DATA_STATE_ACTIVE;
2012*7917SReza.Sabdar@Sun.COM 
2013*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_operation = NDMP_DATA_OP_BACKUP;
2014*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_abort = FALSE;
2015*7917SReza.Sabdar@Sun.COM 
2016*7917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "starting backup");
2017*7917SReza.Sabdar@Sun.COM 
2018*7917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
2019*7917SReza.Sabdar@Sun.COM 	if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
2020*7917SReza.Sabdar@Sun.COM 	    &reply) < 0) {
2021*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Sending data_start_backup reply");
2022*7917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
2023*7917SReza.Sabdar@Sun.COM 		if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
2024*7917SReza.Sabdar@Sun.COM 			/*
2025*7917SReza.Sabdar@Sun.COM 			 * ndmpcopy: we use the same socket for the mover,
2026*7917SReza.Sabdar@Sun.COM 			 * so expect to close when mover is done!
2027*7917SReza.Sabdar@Sun.COM 			 */
2028*7917SReza.Sabdar@Sun.COM 			if (session->ns_data.dd_sock !=
2029*7917SReza.Sabdar@Sun.COM 			    session->ns_mover.md_sock)
2030*7917SReza.Sabdar@Sun.COM 				(void) close(session->ns_data.dd_sock);
2031*7917SReza.Sabdar@Sun.COM 
2032*7917SReza.Sabdar@Sun.COM 			session->ns_data.dd_sock = -1;
2033*7917SReza.Sabdar@Sun.COM 		} else
2034*7917SReza.Sabdar@Sun.COM 			ndmpd_mover_error(session,
2035*7917SReza.Sabdar@Sun.COM 			    NDMP_MOVER_HALT_CONNECT_CLOSED);
2036*7917SReza.Sabdar@Sun.COM 		return (NDMP_NO_ERR);
2037*7917SReza.Sabdar@Sun.COM 	}
2038*7917SReza.Sabdar@Sun.COM 
2039*7917SReza.Sabdar@Sun.COM 	/*
2040*7917SReza.Sabdar@Sun.COM 	 * perform the backup
2041*7917SReza.Sabdar@Sun.COM 	 *
2042*7917SReza.Sabdar@Sun.COM 	 * Cannot wait for the thread to exit as we are replying to the
2043*7917SReza.Sabdar@Sun.COM 	 * client request here.
2044*7917SReza.Sabdar@Sun.COM 	 */
2045*7917SReza.Sabdar@Sun.COM 	(void) pthread_create(NULL, NULL,
2046*7917SReza.Sabdar@Sun.COM 	    (funct_t)session->ns_data.dd_module.dm_start_func,
2047*7917SReza.Sabdar@Sun.COM 	    params);
2048*7917SReza.Sabdar@Sun.COM 
2049*7917SReza.Sabdar@Sun.COM 	return (NDMP_NO_ERR);
2050*7917SReza.Sabdar@Sun.COM }
2051*7917SReza.Sabdar@Sun.COM 
2052*7917SReza.Sabdar@Sun.COM 
2053*7917SReza.Sabdar@Sun.COM /*
2054*7917SReza.Sabdar@Sun.COM  * start_recover
2055*7917SReza.Sabdar@Sun.COM  *
2056*7917SReza.Sabdar@Sun.COM  * The main recover/restore function
2057*7917SReza.Sabdar@Sun.COM  *
2058*7917SReza.Sabdar@Sun.COM  * Parameters:
2059*7917SReza.Sabdar@Sun.COM  *   session   (input) - session pointer.
2060*7917SReza.Sabdar@Sun.COM  *   bu_type   (input) - backup type.
2061*7917SReza.Sabdar@Sun.COM  *   env_val   (input) - environment variable array.
2062*7917SReza.Sabdar@Sun.COM  *   env_len   (input) - length of env_val.
2063*7917SReza.Sabdar@Sun.COM  *   nlist_val (input) - list of files
2064*7917SReza.Sabdar@Sun.COM  *   nlist_len (input) - length of nlist_val
2065*7917SReza.Sabdar@Sun.COM  *
2066*7917SReza.Sabdar@Sun.COM  * Returns:
2067*7917SReza.Sabdar@Sun.COM  *   NDMP_NO_ERR - recover successfully started.
2068*7917SReza.Sabdar@Sun.COM  *   otherwise - error code of backup start error.
2069*7917SReza.Sabdar@Sun.COM  */
2070*7917SReza.Sabdar@Sun.COM static ndmp_error
2071*7917SReza.Sabdar@Sun.COM start_recover(ndmpd_session_t *session, char *bu_type, ndmp_pval *env_val,
2072*7917SReza.Sabdar@Sun.COM     ulong_t env_len, ndmp_name *nlist_val, ulong_t nlist_len)
2073*7917SReza.Sabdar@Sun.COM {
2074*7917SReza.Sabdar@Sun.COM 	ndmp_data_start_recover_reply_v2 reply;
2075*7917SReza.Sabdar@Sun.COM 	ndmpd_module_params_t *params;
2076*7917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
2077*7917SReza.Sabdar@Sun.COM 	int err;
2078*7917SReza.Sabdar@Sun.COM 
2079*7917SReza.Sabdar@Sun.COM 	if (session->ns_data.dd_state != NDMP_DATA_STATE_IDLE) {
2080*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Can't start new recover in current state.");
2081*7917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_STATE_ERR);
2082*7917SReza.Sabdar@Sun.COM 	}
2083*7917SReza.Sabdar@Sun.COM 
2084*7917SReza.Sabdar@Sun.COM 	if (strcmp(bu_type, NDMP_DUMP_TYPE) != 0 &&
2085*7917SReza.Sabdar@Sun.COM 	    strcmp(bu_type, NDMP_TAR_TYPE) != 0) {
2086*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Invalid backup type: %s.", bu_type);
2087*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_ERR, "Supported backup types are tar and dump.");
2088*7917SReza.Sabdar@Sun.COM 		return (NDMP_ILLEGAL_ARGS_ERR);
2089*7917SReza.Sabdar@Sun.COM 	}
2090*7917SReza.Sabdar@Sun.COM 
2091*7917SReza.Sabdar@Sun.COM 	reply.error = ndmpd_save_env(session, env_val, env_len);
2092*7917SReza.Sabdar@Sun.COM 	if (reply.error != NDMP_NO_ERR)
2093*7917SReza.Sabdar@Sun.COM 		return (NDMP_NO_MEM_ERR);
2094*7917SReza.Sabdar@Sun.COM 
2095*7917SReza.Sabdar@Sun.COM 	reply.error = ndmpd_save_nlist_v2(session, nlist_val, nlist_len);
2096*7917SReza.Sabdar@Sun.COM 	if (reply.error != NDMP_NO_ERR)
2097*7917SReza.Sabdar@Sun.COM 		return (NDMP_NO_MEM_ERR);
2098*7917SReza.Sabdar@Sun.COM 
2099*7917SReza.Sabdar@Sun.COM 	nlp = ndmp_get_nlp(session);
2100*7917SReza.Sabdar@Sun.COM 	NDMP_FREE(nlp->nlp_params);
2101*7917SReza.Sabdar@Sun.COM 	params = nlp->nlp_params = ndmp_malloc(sizeof (ndmpd_module_params_t));
2102*7917SReza.Sabdar@Sun.COM 	if (params == NULL)
2103*7917SReza.Sabdar@Sun.COM 		return (NDMP_NO_MEM_ERR);
2104*7917SReza.Sabdar@Sun.COM 
2105*7917SReza.Sabdar@Sun.COM 	/*
2106*7917SReza.Sabdar@Sun.COM 	 * Setup restore parameters.
2107*7917SReza.Sabdar@Sun.COM 	 */
2108*7917SReza.Sabdar@Sun.COM 	params->mp_daemon_cookie = (void *)session;
2109*7917SReza.Sabdar@Sun.COM 	params->mp_module_cookie = &session->ns_data.dd_module.dm_module_cookie;
2110*7917SReza.Sabdar@Sun.COM 	params->mp_protocol_version = session->ns_protocol_version;
2111*7917SReza.Sabdar@Sun.COM 	params->mp_operation = NDMP_DATA_OP_RECOVER;
2112*7917SReza.Sabdar@Sun.COM 	params->mp_get_env_func = ndmpd_api_get_env;
2113*7917SReza.Sabdar@Sun.COM 	params->mp_add_env_func = ndmpd_api_add_env;
2114*7917SReza.Sabdar@Sun.COM 	params->mp_get_name_func = ndmpd_api_get_name;
2115*7917SReza.Sabdar@Sun.COM 	params->mp_dispatch_func = ndmpd_api_dispatch;
2116*7917SReza.Sabdar@Sun.COM 	params->mp_done_func = ndmpd_api_done_v2;
2117*7917SReza.Sabdar@Sun.COM 	params->mp_log_func = ndmpd_api_log_v2;
2118*7917SReza.Sabdar@Sun.COM 	params->mp_add_file_handler_func = ndmpd_api_add_file_handler;
2119*7917SReza.Sabdar@Sun.COM 	params->mp_remove_file_handler_func = ndmpd_api_remove_file_handler;
2120*7917SReza.Sabdar@Sun.COM 	params->mp_write_func = 0;
2121*7917SReza.Sabdar@Sun.COM 	params->mp_file_history_path_func = 0;
2122*7917SReza.Sabdar@Sun.COM 	params->mp_file_history_dir_func = 0;
2123*7917SReza.Sabdar@Sun.COM 	params->mp_file_history_node_func = 0;
2124*7917SReza.Sabdar@Sun.COM 	params->mp_read_func = ndmpd_api_read_v2;
2125*7917SReza.Sabdar@Sun.COM 	params->mp_seek_func = ndmpd_api_seek_v2;
2126*7917SReza.Sabdar@Sun.COM 	params->mp_file_recovered_func = ndmpd_api_file_recovered_v2;
2127*7917SReza.Sabdar@Sun.COM 	params->mp_stats = &session->ns_data.dd_module.dm_stats;
2128*7917SReza.Sabdar@Sun.COM 
2129*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_module_cookie = 0;
2130*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_start_func = ndmpd_tar_restore_starter;
2131*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_abort_func = ndmpd_tar_restore_abort;
2132*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_bytes_remaining = 0;
2133*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_module.dm_stats.ms_est_time_remaining = 0;
2134*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_offset = 0;
2135*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_read_length = 0;
2136*7917SReza.Sabdar@Sun.COM 
2137*7917SReza.Sabdar@Sun.COM 	if ((err = ndmp_restore_extract_params(session,
2138*7917SReza.Sabdar@Sun.COM 	    params)) != NDMP_NO_ERR) {
2139*7917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
2140*7917SReza.Sabdar@Sun.COM 		return (err);
2141*7917SReza.Sabdar@Sun.COM 	}
2142*7917SReza.Sabdar@Sun.COM 
2143*7917SReza.Sabdar@Sun.COM 	err = ndmpd_mover_connect(session, NDMP_MOVER_MODE_WRITE);
2144*7917SReza.Sabdar@Sun.COM 	if (err != NDMP_NO_ERR) {
2145*7917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
2146*7917SReza.Sabdar@Sun.COM 		return (err);
2147*7917SReza.Sabdar@Sun.COM 	}
2148*7917SReza.Sabdar@Sun.COM 
2149*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_state = NDMP_DATA_STATE_ACTIVE;
2150*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_operation = NDMP_DATA_OP_RECOVER;
2151*7917SReza.Sabdar@Sun.COM 	session->ns_data.dd_abort = FALSE;
2152*7917SReza.Sabdar@Sun.COM 
2153*7917SReza.Sabdar@Sun.COM 	reply.error = NDMP_NO_ERR;
2154*7917SReza.Sabdar@Sun.COM 	if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
2155*7917SReza.Sabdar@Sun.COM 	    &reply) < 0) {
2156*7917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "Sending data_start_recover reply");
2157*7917SReza.Sabdar@Sun.COM 		NDMP_FREE(nlp->nlp_params);
2158*7917SReza.Sabdar@Sun.COM 		if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
2159*7917SReza.Sabdar@Sun.COM 			/*
2160*7917SReza.Sabdar@Sun.COM 			 * ndmpcopy: we use the same socket for the mover,
2161*7917SReza.Sabdar@Sun.COM 			 * so expect to close when mover is done!
2162*7917SReza.Sabdar@Sun.COM 			 */
2163*7917SReza.Sabdar@Sun.COM 			if (session->ns_data.dd_sock !=
2164*7917SReza.Sabdar@Sun.COM 			    session->ns_mover.md_sock)
2165*7917SReza.Sabdar@Sun.COM 				(void) close(session->ns_data.dd_sock);
2166*7917SReza.Sabdar@Sun.COM 
2167*7917SReza.Sabdar@Sun.COM 			session->ns_data.dd_sock = -1;
2168*7917SReza.Sabdar@Sun.COM 		} else {
2169*7917SReza.Sabdar@Sun.COM 			ndmpd_mover_error(session,
2170*7917SReza.Sabdar@Sun.COM 			    NDMP_MOVER_HALT_CONNECT_CLOSED);
2171*7917SReza.Sabdar@Sun.COM 		}
2172*7917SReza.Sabdar@Sun.COM 		return (NDMP_NO_ERR);
2173*7917SReza.Sabdar@Sun.COM 	}
2174*7917SReza.Sabdar@Sun.COM 
2175*7917SReza.Sabdar@Sun.COM 
2176*7917SReza.Sabdar@Sun.COM 	/*
2177*7917SReza.Sabdar@Sun.COM 	 * perform the restore
2178*7917SReza.Sabdar@Sun.COM 	 *
2179*7917SReza.Sabdar@Sun.COM 	 * Cannot wait for the thread to exit as we are replying the
2180*7917SReza.Sabdar@Sun.COM 	 * client request here.
2181*7917SReza.Sabdar@Sun.COM 	 */
2182*7917SReza.Sabdar@Sun.COM 	(void) pthread_create(NULL, NULL,
2183*7917SReza.Sabdar@Sun.COM 	    (funct_t)session->ns_data.dd_module.dm_start_func,
2184*7917SReza.Sabdar@Sun.COM 	    params);
2185*7917SReza.Sabdar@Sun.COM 
2186*7917SReza.Sabdar@Sun.COM 	return (NDMP_NO_ERR);
2187*7917SReza.Sabdar@Sun.COM }
2188*7917SReza.Sabdar@Sun.COM 
2189*7917SReza.Sabdar@Sun.COM 
2190*7917SReza.Sabdar@Sun.COM /*
2191*7917SReza.Sabdar@Sun.COM  * ndmpd_data_get_info
2192*7917SReza.Sabdar@Sun.COM  *
2193*7917SReza.Sabdar@Sun.COM  * Return the total number of bytes processed
2194*7917SReza.Sabdar@Sun.COM  *
2195*7917SReza.Sabdar@Sun.COM  * Parameters:
2196*7917SReza.Sabdar@Sun.COM  *   session   (input) - session pointer.
2197*7917SReza.Sabdar@Sun.COM  *
2198*7917SReza.Sabdar@Sun.COM  * Returns:
2199*7917SReza.Sabdar@Sun.COM  *   the number of bytes processed
2200*7917SReza.Sabdar@Sun.COM  */
2201*7917SReza.Sabdar@Sun.COM static u_longlong_t
2202*7917SReza.Sabdar@Sun.COM ndmpd_data_get_info(ndmpd_session_t *session)
2203*7917SReza.Sabdar@Sun.COM {
2204*7917SReza.Sabdar@Sun.COM 	ndmp_lbr_params_t *nlp;
2205*7917SReza.Sabdar@Sun.COM 
2206*7917SReza.Sabdar@Sun.COM 	nlp = ndmp_get_nlp(session);
2207*7917SReza.Sabdar@Sun.COM 	if (nlp == NULL)
2208*7917SReza.Sabdar@Sun.COM 		return ((u_longlong_t)0);
2209*7917SReza.Sabdar@Sun.COM 
2210*7917SReza.Sabdar@Sun.COM 	if (nlp->nlp_jstat == NULL)
2211*7917SReza.Sabdar@Sun.COM 		return (nlp->nlp_bytes_total);
2212*7917SReza.Sabdar@Sun.COM 
2213*7917SReza.Sabdar@Sun.COM 	return ((u_longlong_t)nlp->nlp_jstat->js_bytes_total);
2214*7917SReza.Sabdar@Sun.COM }
2215