xref: /illumos-gate/usr/src/cmd/ndmpd/ndmp/ndmpd_util.c (revision 2654012f83cec5dc15b61dfe3e4a4915f186e7a6)
1*2654012fSReza Sabdar /*
2*2654012fSReza Sabdar  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3*2654012fSReza Sabdar  * Use is subject to license terms.
4*2654012fSReza Sabdar  */
5*2654012fSReza Sabdar 
6*2654012fSReza Sabdar /*
7*2654012fSReza Sabdar  * BSD 3 Clause License
8*2654012fSReza Sabdar  *
9*2654012fSReza Sabdar  * Copyright (c) 2007, The Storage Networking Industry Association.
10*2654012fSReza Sabdar  *
11*2654012fSReza Sabdar  * Redistribution and use in source and binary forms, with or without
12*2654012fSReza Sabdar  * modification, are permitted provided that the following conditions
13*2654012fSReza Sabdar  * are met:
14*2654012fSReza Sabdar  * 	- Redistributions of source code must retain the above copyright
15*2654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer.
16*2654012fSReza Sabdar  *
17*2654012fSReza Sabdar  * 	- Redistributions in binary form must reproduce the above copyright
18*2654012fSReza Sabdar  *	  notice, this list of conditions and the following disclaimer in
19*2654012fSReza Sabdar  *	  the documentation and/or other materials provided with the
20*2654012fSReza Sabdar  *	  distribution.
21*2654012fSReza Sabdar  *
22*2654012fSReza Sabdar  *	- Neither the name of The Storage Networking Industry Association (SNIA)
23*2654012fSReza Sabdar  *	  nor the names of its contributors may be used to endorse or promote
24*2654012fSReza Sabdar  *	  products derived from this software without specific prior written
25*2654012fSReza Sabdar  *	  permission.
26*2654012fSReza Sabdar  *
27*2654012fSReza Sabdar  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28*2654012fSReza Sabdar  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29*2654012fSReza Sabdar  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30*2654012fSReza Sabdar  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31*2654012fSReza Sabdar  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32*2654012fSReza Sabdar  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33*2654012fSReza Sabdar  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34*2654012fSReza Sabdar  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35*2654012fSReza Sabdar  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36*2654012fSReza Sabdar  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37*2654012fSReza Sabdar  * POSSIBILITY OF SUCH DAMAGE.
38*2654012fSReza Sabdar  */
39*2654012fSReza Sabdar /* Copyright (c) 2007, The Storage Networking Industry Association. */
40*2654012fSReza Sabdar /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
41*2654012fSReza Sabdar 
42*2654012fSReza Sabdar #include <sys/types.h>
43*2654012fSReza Sabdar #include <sys/socket.h>
44*2654012fSReza Sabdar #include <assert.h>
45*2654012fSReza Sabdar #include <ctype.h>
46*2654012fSReza Sabdar #include <errno.h>
47*2654012fSReza Sabdar #include <stdio.h>
48*2654012fSReza Sabdar #include <stdlib.h>
49*2654012fSReza Sabdar #include <unistd.h>
50*2654012fSReza Sabdar #include <strings.h>
51*2654012fSReza Sabdar #include <time.h>
52*2654012fSReza Sabdar #include <libgen.h>
53*2654012fSReza Sabdar #include "ndmpd.h"
54*2654012fSReza Sabdar #include <bitmap.h>
55*2654012fSReza Sabdar #include <sys/queue.h>
56*2654012fSReza Sabdar #include <sys/socket.h>
57*2654012fSReza Sabdar #include <netinet/in.h>
58*2654012fSReza Sabdar #include <netinet/tcp.h>
59*2654012fSReza Sabdar #include <arpa/inet.h>
60*2654012fSReza Sabdar #include <sys/socketvar.h>
61*2654012fSReza Sabdar #include <net/if.h>
62*2654012fSReza Sabdar #include <netdb.h>
63*2654012fSReza Sabdar #include <sys/filio.h>
64*2654012fSReza Sabdar #include <sys/mtio.h>
65*2654012fSReza Sabdar #include <sys/scsi/impl/uscsi.h>
66*2654012fSReza Sabdar #include <sys/scsi/scsi.h>
67*2654012fSReza Sabdar #include "tlm.h"
68*2654012fSReza Sabdar 
69*2654012fSReza Sabdar /*
70*2654012fSReza Sabdar  * Mutex to protect Nlp
71*2654012fSReza Sabdar  */
72*2654012fSReza Sabdar mutex_t nlp_mtx;
73*2654012fSReza Sabdar 
74*2654012fSReza Sabdar /*
75*2654012fSReza Sabdar  * Patchable socket buffer sizes in kilobytes.
76*2654012fSReza Sabdar  * ssb: send buffer size.
77*2654012fSReza Sabdar  * rsb: receive buffer size.
78*2654012fSReza Sabdar  */
79*2654012fSReza Sabdar int ndmp_sbs = 60;
80*2654012fSReza Sabdar int ndmp_rbs = 60;
81*2654012fSReza Sabdar 
82*2654012fSReza Sabdar 
83*2654012fSReza Sabdar /*
84*2654012fSReza Sabdar  * Force to backup all the intermediate directories leading to an object
85*2654012fSReza Sabdar  * to be backed up in 'dump' format backup.
86*2654012fSReza Sabdar  */
87*2654012fSReza Sabdar boolean_t ndmp_dump_path_node = FALSE;
88*2654012fSReza Sabdar 
89*2654012fSReza Sabdar 
90*2654012fSReza Sabdar /*
91*2654012fSReza Sabdar  * Force to backup all the intermediate directories leading to an object
92*2654012fSReza Sabdar  * to be backed up in 'tar' format backup.
93*2654012fSReza Sabdar  */
94*2654012fSReza Sabdar boolean_t ndmp_tar_path_node = FALSE;
95*2654012fSReza Sabdar 
96*2654012fSReza Sabdar 
97*2654012fSReza Sabdar /*
98*2654012fSReza Sabdar  * Should the 'st_ctime' be ignored during incremental level backup?
99*2654012fSReza Sabdar  */
100*2654012fSReza Sabdar boolean_t ndmp_ignore_ctime = FALSE;
101*2654012fSReza Sabdar 
102*2654012fSReza Sabdar /*
103*2654012fSReza Sabdar  * Should the 'st_lmtime' be included during incremental level backup?
104*2654012fSReza Sabdar  */
105*2654012fSReza Sabdar boolean_t ndmp_include_lmtime = FALSE;
106*2654012fSReza Sabdar 
107*2654012fSReza Sabdar /*
108*2654012fSReza Sabdar  * Force to send the file history node entries along with the file history
109*2654012fSReza Sabdar  * dir entries for all directories containing the changed files to the client
110*2654012fSReza Sabdar  * for incremental backup.
111*2654012fSReza Sabdar  *
112*2654012fSReza Sabdar  * Note: This variable is added to support Bakbone Software's Netvault DMA
113*2654012fSReza Sabdar  * which expects to get the FH ADD NODES for all upper directories which
114*2654012fSReza Sabdar  * contain the changed files in incremental backup along with the FH ADD DIRS.
115*2654012fSReza Sabdar  */
116*2654012fSReza Sabdar boolean_t ndmp_fhinode = FALSE;
117*2654012fSReza Sabdar 
118*2654012fSReza Sabdar /*
119*2654012fSReza Sabdar  * Maximum permitted sequence number in the token-based backup.  The
120*2654012fSReza Sabdar  * value of this variable can be changed by the administrator and is
121*2654012fSReza Sabdar  * saved in the NDMP configuration file.
122*2654012fSReza Sabdar  */
123*2654012fSReza Sabdar static int ndmp_max_tok_seq = NDMP_MAX_TOKSEQ;
124*2654012fSReza Sabdar 
125*2654012fSReza Sabdar /*
126*2654012fSReza Sabdar  * Force backup directories in incremental backups.  If the
127*2654012fSReza Sabdar  * directory is not modified itself, it's not backed up by
128*2654012fSReza Sabdar  * default.
129*2654012fSReza Sabdar  */
130*2654012fSReza Sabdar int ndmp_force_bk_dirs = 0;
131*2654012fSReza Sabdar 
132*2654012fSReza Sabdar /*
133*2654012fSReza Sabdar  * Keeps track of the open SCSI (including tape and robot) devices.
134*2654012fSReza Sabdar  * When a SCSI device is opened its name must be added to this list and
135*2654012fSReza Sabdar  * when it's closed its name must be removed from this list.  The main
136*2654012fSReza Sabdar  * purpose of this list is the robot device.  If the robot devices are not
137*2654012fSReza Sabdar  * attached in SASD layer, Local Backup won't see them. If they are
138*2654012fSReza Sabdar  * attached and we open the robot devices, then wrong commands are sent
139*2654012fSReza Sabdar  * to robot by SASD since it assumes that the robot is a tape (sequential
140*2654012fSReza Sabdar  * access) device.
141*2654012fSReza Sabdar  */
142*2654012fSReza Sabdar struct open_list {
143*2654012fSReza Sabdar 	LIST_ENTRY(open_list) ol_q;
144*2654012fSReza Sabdar 	int ol_nref;
145*2654012fSReza Sabdar 	char *ol_devnm;
146*2654012fSReza Sabdar 	int ol_sid;
147*2654012fSReza Sabdar 	int ol_lun;
148*2654012fSReza Sabdar 	int ol_fd;
149*2654012fSReza Sabdar 	ndmp_connection_t *cl_conn;
150*2654012fSReza Sabdar };
151*2654012fSReza Sabdar LIST_HEAD(ol_head, open_list);
152*2654012fSReza Sabdar 
153*2654012fSReza Sabdar 
154*2654012fSReza Sabdar /*
155*2654012fSReza Sabdar  * Head of the opened SCSI devices list.
156*2654012fSReza Sabdar  */
157*2654012fSReza Sabdar static struct ol_head ol_head;
158*2654012fSReza Sabdar 
159*2654012fSReza Sabdar mutex_t ol_mutex = DEFAULTMUTEX;
160*2654012fSReza Sabdar 
161*2654012fSReza Sabdar 
162*2654012fSReza Sabdar /*
163*2654012fSReza Sabdar  * List of things to be exluded from backup.
164*2654012fSReza Sabdar  */
165*2654012fSReza Sabdar static char *exls[] = {
166*2654012fSReza Sabdar 	EXCL_PROC,
167*2654012fSReza Sabdar 	EXCL_TMP,
168*2654012fSReza Sabdar 	NULL, /* reserved for a copy of the "backup.directory" */
169*2654012fSReza Sabdar 	NULL
170*2654012fSReza Sabdar };
171*2654012fSReza Sabdar 
172*2654012fSReza Sabdar 
173*2654012fSReza Sabdar /*
174*2654012fSReza Sabdar  * The counter for creating unique names with "ndmp.%d" format.
175*2654012fSReza Sabdar  */
176*2654012fSReza Sabdar #define	NDMP_RCF_BASENAME	"ndmp."
177*2654012fSReza Sabdar static int ndmp_job_cnt = 0;
178*2654012fSReza Sabdar 
179*2654012fSReza Sabdar static int scsi_test_unit_ready(int dev_id);
180*2654012fSReza Sabdar 
181*2654012fSReza Sabdar /*
182*2654012fSReza Sabdar  * ndmpd_add_file_handler
183*2654012fSReza Sabdar  *
184*2654012fSReza Sabdar  * Adds a file handler to the file handler list.
185*2654012fSReza Sabdar  * The file handler list is used by ndmpd_api_dispatch.
186*2654012fSReza Sabdar  *
187*2654012fSReza Sabdar  * Parameters:
188*2654012fSReza Sabdar  *   session (input) - session pointer.
189*2654012fSReza Sabdar  *   cookie  (input) - opaque data to be passed to file hander when called.
190*2654012fSReza Sabdar  *   fd      (input) - file descriptor.
191*2654012fSReza Sabdar  *   mode    (input) - bitmask of the following:
192*2654012fSReza Sabdar  *		     1 = watch file for ready for reading
193*2654012fSReza Sabdar  *		     2 = watch file for ready for writing
194*2654012fSReza Sabdar  *		     4 = watch file for exception
195*2654012fSReza Sabdar  *   class   (input) - handler class. (HC_CLIENT, HC_MOVER, HC_MODULE)
196*2654012fSReza Sabdar  *   func    (input) - function to call when the file meets one of the
197*2654012fSReza Sabdar  *		     conditions specified by mode.
198*2654012fSReza Sabdar  *
199*2654012fSReza Sabdar  * Returns:
200*2654012fSReza Sabdar  *   0 - success.
201*2654012fSReza Sabdar  *  -1 - error.
202*2654012fSReza Sabdar  */
203*2654012fSReza Sabdar int
204*2654012fSReza Sabdar ndmpd_add_file_handler(ndmpd_session_t *session, void *cookie, int fd,
205*2654012fSReza Sabdar     ulong_t mode, ulong_t class, ndmpd_file_handler_func_t *func)
206*2654012fSReza Sabdar {
207*2654012fSReza Sabdar 	ndmpd_file_handler_t *new;
208*2654012fSReza Sabdar 
209*2654012fSReza Sabdar 	new = ndmp_malloc(sizeof (ndmpd_file_handler_t));
210*2654012fSReza Sabdar 	if (new == 0)
211*2654012fSReza Sabdar 		return (-1);
212*2654012fSReza Sabdar 
213*2654012fSReza Sabdar 	new->fh_cookie = cookie;
214*2654012fSReza Sabdar 	new->fh_fd = fd;
215*2654012fSReza Sabdar 	new->fh_mode = mode;
216*2654012fSReza Sabdar 	new->fh_class = class;
217*2654012fSReza Sabdar 	new->fh_func = func;
218*2654012fSReza Sabdar 	new->fh_next = session->ns_file_handler_list;
219*2654012fSReza Sabdar 	session->ns_file_handler_list = new;
220*2654012fSReza Sabdar 	return (0);
221*2654012fSReza Sabdar }
222*2654012fSReza Sabdar 
223*2654012fSReza Sabdar 
224*2654012fSReza Sabdar /*
225*2654012fSReza Sabdar  * ndmpd_remove_file_handler
226*2654012fSReza Sabdar  *
227*2654012fSReza Sabdar  * Removes a file handler from the file handler list.
228*2654012fSReza Sabdar  *
229*2654012fSReza Sabdar  * Parameters:
230*2654012fSReza Sabdar  *   session (input) - session pointer.
231*2654012fSReza Sabdar  *   fd      (input) - file descriptor.
232*2654012fSReza Sabdar  *
233*2654012fSReza Sabdar  * Returns:
234*2654012fSReza Sabdar  *   0 - success.
235*2654012fSReza Sabdar  *  -1 - error.
236*2654012fSReza Sabdar  */
237*2654012fSReza Sabdar int
238*2654012fSReza Sabdar ndmpd_remove_file_handler(ndmpd_session_t *session, int fd)
239*2654012fSReza Sabdar {
240*2654012fSReza Sabdar 	ndmpd_file_handler_t **last;
241*2654012fSReza Sabdar 	ndmpd_file_handler_t *handler;
242*2654012fSReza Sabdar 
243*2654012fSReza Sabdar 	last = &session->ns_file_handler_list;
244*2654012fSReza Sabdar 	while (*last != 0) {
245*2654012fSReza Sabdar 		handler = *last;
246*2654012fSReza Sabdar 
247*2654012fSReza Sabdar 		if (handler->fh_fd == fd) {
248*2654012fSReza Sabdar 			*last = handler->fh_next;
249*2654012fSReza Sabdar 			(void) free(handler);
250*2654012fSReza Sabdar 			return (1);
251*2654012fSReza Sabdar 		}
252*2654012fSReza Sabdar 		last = &handler->fh_next;
253*2654012fSReza Sabdar 	}
254*2654012fSReza Sabdar 
255*2654012fSReza Sabdar 	return (0);
256*2654012fSReza Sabdar }
257*2654012fSReza Sabdar 
258*2654012fSReza Sabdar 
259*2654012fSReza Sabdar /*
260*2654012fSReza Sabdar  * ndmp_connection_closed
261*2654012fSReza Sabdar  *
262*2654012fSReza Sabdar  * If the connection closed or not.
263*2654012fSReza Sabdar  *
264*2654012fSReza Sabdar  * Parameters:
265*2654012fSReza Sabdar  *   fd (input) : file descriptor
266*2654012fSReza Sabdar  *
267*2654012fSReza Sabdar  * Returns:
268*2654012fSReza Sabdar  *   0  - connection is still valid
269*2654012fSReza Sabdar  *   1  - connection is not valid anymore
270*2654012fSReza Sabdar  *   -1 - Internal kernel error
271*2654012fSReza Sabdar  */
272*2654012fSReza Sabdar int
273*2654012fSReza Sabdar ndmp_connection_closed(int fd)
274*2654012fSReza Sabdar {
275*2654012fSReza Sabdar 	fd_set fds;
276*2654012fSReza Sabdar 	int closed, ret;
277*2654012fSReza Sabdar 	struct timeval timeout;
278*2654012fSReza Sabdar 
279*2654012fSReza Sabdar 	if (fd < 0) /* We are not using the mover */
280*2654012fSReza Sabdar 		return (-1);
281*2654012fSReza Sabdar 
282*2654012fSReza Sabdar 	timeout.tv_sec = 0;
283*2654012fSReza Sabdar 	timeout.tv_usec = 1000;
284*2654012fSReza Sabdar 
285*2654012fSReza Sabdar 	FD_ZERO(&fds);
286*2654012fSReza Sabdar 	FD_SET(fd, &fds);
287*2654012fSReza Sabdar 	ret = select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
288*2654012fSReza Sabdar 
289*2654012fSReza Sabdar 	closed = (ret == -1 && errno == EBADF);
290*2654012fSReza Sabdar 
291*2654012fSReza Sabdar 	return (closed);
292*2654012fSReza Sabdar }
293*2654012fSReza Sabdar 
294*2654012fSReza Sabdar /*
295*2654012fSReza Sabdar  * ndmp_check_mover_state
296*2654012fSReza Sabdar  *
297*2654012fSReza Sabdar  * Checks the mover connection status and sends an appropriate
298*2654012fSReza Sabdar  * NDMP message to client based on that.
299*2654012fSReza Sabdar  *
300*2654012fSReza Sabdar  * Parameters:
301*2654012fSReza Sabdar  *   ndmpd_session_t *session (input) : session pointer
302*2654012fSReza Sabdar  *
303*2654012fSReza Sabdar  * Returns:
304*2654012fSReza Sabdar  *   void.
305*2654012fSReza Sabdar  */
306*2654012fSReza Sabdar void
307*2654012fSReza Sabdar ndmp_check_mover_state(ndmpd_session_t *session)
308*2654012fSReza Sabdar {
309*2654012fSReza Sabdar 	int moverfd;
310*2654012fSReza Sabdar 	/*
311*2654012fSReza Sabdar 	 * NDMPV3 Spec (Three-way restore):
312*2654012fSReza Sabdar 	 * Once all of the files have been recovered, NDMP DATA Server closes
313*2654012fSReza Sabdar 	 * the connection to the mover on the NDMP TAPE Server. THEN
314*2654012fSReza Sabdar 	 * The NDMP client should receive an NDMP_NOTIFY_MOVER_HALTED message
315*2654012fSReza Sabdar 	 * with an NDMP_MOVER_CONNECT_CLOSED reason from the NDMP TAPE Server
316*2654012fSReza Sabdar 	 */
317*2654012fSReza Sabdar 	moverfd = session->ns_mover.md_sock;
318*2654012fSReza Sabdar 	/* If connection is closed by the peer */
319*2654012fSReza Sabdar 	if (moverfd >= 0 &&
320*2654012fSReza Sabdar 	    session->ns_mover.md_mode == NDMP_MOVER_MODE_WRITE) {
321*2654012fSReza Sabdar 		int closed, reason;
322*2654012fSReza Sabdar 
323*2654012fSReza Sabdar 		closed = ndmp_connection_closed(moverfd);
324*2654012fSReza Sabdar 		if (closed) {
325*2654012fSReza Sabdar 			/* Connection closed or internal error */
326*2654012fSReza Sabdar 			if (closed > 0) {
327*2654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
328*2654012fSReza Sabdar 				    "ndmp mover: connection closed by peer");
329*2654012fSReza Sabdar 				reason = NDMP_MOVER_HALT_CONNECT_CLOSED;
330*2654012fSReza Sabdar 			} else {
331*2654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
332*2654012fSReza Sabdar 				    "ndmp mover: Internal error");
333*2654012fSReza Sabdar 				reason = NDMP_MOVER_HALT_INTERNAL_ERROR;
334*2654012fSReza Sabdar 			}
335*2654012fSReza Sabdar 			ndmpd_mover_error(session, reason);
336*2654012fSReza Sabdar 
337*2654012fSReza Sabdar 		}
338*2654012fSReza Sabdar 	}
339*2654012fSReza Sabdar }
340*2654012fSReza Sabdar 
341*2654012fSReza Sabdar 
342*2654012fSReza Sabdar /*
343*2654012fSReza Sabdar  * ndmpd_select
344*2654012fSReza Sabdar  *
345*2654012fSReza Sabdar  * Calls select on the the set of file descriptors from the
346*2654012fSReza Sabdar  * file handler list masked by the fd_class argument.
347*2654012fSReza Sabdar  * Calls the file handler function for each
348*2654012fSReza Sabdar  * file descriptor that is ready for I/O.
349*2654012fSReza Sabdar  *
350*2654012fSReza Sabdar  * Parameters:
351*2654012fSReza Sabdar  *   session (input) - session pointer.
352*2654012fSReza Sabdar  *   block   (input) - if TRUE, ndmpd_select waits until at least one
353*2654012fSReza Sabdar  *		     file descriptor is ready for I/O. Otherwise,
354*2654012fSReza Sabdar  *		     it returns immediately if no file descriptors are
355*2654012fSReza Sabdar  *		     ready for I/O.
356*2654012fSReza Sabdar  *   class_mask (input) - bit mask of handler classes to be examined.
357*2654012fSReza Sabdar  *		     Provides for excluding some of the handlers from
358*2654012fSReza Sabdar  *		     being called.
359*2654012fSReza Sabdar  *
360*2654012fSReza Sabdar  * Returns:
361*2654012fSReza Sabdar  *  -1 - error.
362*2654012fSReza Sabdar  *   0 - no handlers were called.
363*2654012fSReza Sabdar  *   1 - at least one handler was called.
364*2654012fSReza Sabdar  */
365*2654012fSReza Sabdar int
366*2654012fSReza Sabdar ndmpd_select(ndmpd_session_t *session, boolean_t block, ulong_t class_mask)
367*2654012fSReza Sabdar {
368*2654012fSReza Sabdar 	fd_set rfds;
369*2654012fSReza Sabdar 	fd_set wfds;
370*2654012fSReza Sabdar 	fd_set efds;
371*2654012fSReza Sabdar 	int n;
372*2654012fSReza Sabdar 	ndmpd_file_handler_t *handler;
373*2654012fSReza Sabdar 	struct timeval timeout;
374*2654012fSReza Sabdar 
375*2654012fSReza Sabdar 	nlp_event_rv_set(session, 0);
376*2654012fSReza Sabdar 
377*2654012fSReza Sabdar 	if (session->ns_file_handler_list == 0)
378*2654012fSReza Sabdar 		return (0);
379*2654012fSReza Sabdar 
380*2654012fSReza Sabdar 
381*2654012fSReza Sabdar 	/*
382*2654012fSReza Sabdar 	 * If select should be blocked, then we poll every ten seconds.
383*2654012fSReza Sabdar 	 * The reason is in case of three-way restore we should be able
384*2654012fSReza Sabdar 	 * to detect if the other end closed the connection or not.
385*2654012fSReza Sabdar 	 * NDMP client(DMA) does not send any information about the connection
386*2654012fSReza Sabdar 	 * that was closed in the other end.
387*2654012fSReza Sabdar 	 */
388*2654012fSReza Sabdar 
389*2654012fSReza Sabdar 	if (block == TRUE)
390*2654012fSReza Sabdar 		timeout.tv_sec = 10;
391*2654012fSReza Sabdar 	else
392*2654012fSReza Sabdar 		timeout.tv_sec = 0;
393*2654012fSReza Sabdar 	timeout.tv_usec = 0;
394*2654012fSReza Sabdar 
395*2654012fSReza Sabdar 	do {
396*2654012fSReza Sabdar 		/* Create the fd_sets for select. */
397*2654012fSReza Sabdar 		FD_ZERO(&rfds);
398*2654012fSReza Sabdar 		FD_ZERO(&wfds);
399*2654012fSReza Sabdar 		FD_ZERO(&efds);
400*2654012fSReza Sabdar 
401*2654012fSReza Sabdar 		for (handler = session->ns_file_handler_list; handler != 0;
402*2654012fSReza Sabdar 		    handler = handler->fh_next) {
403*2654012fSReza Sabdar 			if ((handler->fh_class & class_mask) == 0)
404*2654012fSReza Sabdar 				continue;
405*2654012fSReza Sabdar 
406*2654012fSReza Sabdar 			if (handler->fh_mode & NDMPD_SELECT_MODE_READ)
407*2654012fSReza Sabdar 				FD_SET(handler->fh_fd, &rfds);
408*2654012fSReza Sabdar 			if (handler->fh_mode & NDMPD_SELECT_MODE_WRITE)
409*2654012fSReza Sabdar 				FD_SET(handler->fh_fd, &wfds);
410*2654012fSReza Sabdar 			if (handler->fh_mode & NDMPD_SELECT_MODE_EXCEPTION)
411*2654012fSReza Sabdar 				FD_SET(handler->fh_fd, &efds);
412*2654012fSReza Sabdar 		}
413*2654012fSReza Sabdar 		ndmp_check_mover_state(session);
414*2654012fSReza Sabdar 		n = select(FD_SETSIZE, &rfds, &wfds, &efds, &timeout);
415*2654012fSReza Sabdar 	} while (n == 0 && block == TRUE);
416*2654012fSReza Sabdar 
417*2654012fSReza Sabdar 	if (n < 0) {
418*2654012fSReza Sabdar 		int connection_fd = ndmp_get_fd(session->ns_connection);
419*2654012fSReza Sabdar 
420*2654012fSReza Sabdar 		if (errno == EINTR)
421*2654012fSReza Sabdar 			return (0);
422*2654012fSReza Sabdar 
423*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Select error: %m");
424*2654012fSReza Sabdar 
425*2654012fSReza Sabdar 		for (handler = session->ns_file_handler_list; handler != 0;
426*2654012fSReza Sabdar 		    handler = handler->fh_next) {
427*2654012fSReza Sabdar 			if ((handler->fh_class & class_mask) == 0)
428*2654012fSReza Sabdar 				continue;
429*2654012fSReza Sabdar 
430*2654012fSReza Sabdar 			if (handler->fh_mode & NDMPD_SELECT_MODE_READ) {
431*2654012fSReza Sabdar 				if (FD_ISSET(handler->fh_fd, &rfds) &&
432*2654012fSReza Sabdar 				    connection_fd == handler->fh_fd)
433*2654012fSReza Sabdar 					session->ns_eof = TRUE;
434*2654012fSReza Sabdar 			}
435*2654012fSReza Sabdar 			if (handler->fh_mode & NDMPD_SELECT_MODE_WRITE) {
436*2654012fSReza Sabdar 				if (FD_ISSET(handler->fh_fd, &wfds) &&
437*2654012fSReza Sabdar 				    connection_fd == handler->fh_fd)
438*2654012fSReza Sabdar 					session->ns_eof = TRUE;
439*2654012fSReza Sabdar 			}
440*2654012fSReza Sabdar 			if (handler->fh_mode & NDMPD_SELECT_MODE_EXCEPTION) {
441*2654012fSReza Sabdar 				if (FD_ISSET(handler->fh_fd, &efds) &&
442*2654012fSReza Sabdar 				    connection_fd == handler->fh_fd)
443*2654012fSReza Sabdar 					session->ns_eof = TRUE;
444*2654012fSReza Sabdar 			}
445*2654012fSReza Sabdar 		}
446*2654012fSReza Sabdar 
447*2654012fSReza Sabdar 		nlp_event_rv_set(session, -1);
448*2654012fSReza Sabdar 		return (-1);
449*2654012fSReza Sabdar 	}
450*2654012fSReza Sabdar 	if (n == 0)
451*2654012fSReza Sabdar 		return (0);
452*2654012fSReza Sabdar 
453*2654012fSReza Sabdar 	handler = session->ns_file_handler_list;
454*2654012fSReza Sabdar 	while (handler != 0) {
455*2654012fSReza Sabdar 		ulong_t mode = 0;
456*2654012fSReza Sabdar 
457*2654012fSReza Sabdar 		if ((handler->fh_class & class_mask) == 0) {
458*2654012fSReza Sabdar 			handler = handler->fh_next;
459*2654012fSReza Sabdar 			continue;
460*2654012fSReza Sabdar 		}
461*2654012fSReza Sabdar 		if (handler->fh_mode & NDMPD_SELECT_MODE_READ) {
462*2654012fSReza Sabdar 			if (FD_ISSET(handler->fh_fd, &rfds)) {
463*2654012fSReza Sabdar 				mode |= NDMPD_SELECT_MODE_READ;
464*2654012fSReza Sabdar 				FD_CLR(handler->fh_fd, &rfds);
465*2654012fSReza Sabdar 			}
466*2654012fSReza Sabdar 		}
467*2654012fSReza Sabdar 		if (handler->fh_mode & NDMPD_SELECT_MODE_WRITE) {
468*2654012fSReza Sabdar 			if (FD_ISSET(handler->fh_fd, &wfds)) {
469*2654012fSReza Sabdar 				mode |= NDMPD_SELECT_MODE_WRITE;
470*2654012fSReza Sabdar 				FD_CLR(handler->fh_fd, &wfds);
471*2654012fSReza Sabdar 			}
472*2654012fSReza Sabdar 		}
473*2654012fSReza Sabdar 		if (handler->fh_mode & NDMPD_SELECT_MODE_EXCEPTION) {
474*2654012fSReza Sabdar 			if (FD_ISSET(handler->fh_fd, &efds)) {
475*2654012fSReza Sabdar 				mode |= NDMPD_SELECT_MODE_EXCEPTION;
476*2654012fSReza Sabdar 				FD_CLR(handler->fh_fd, &efds);
477*2654012fSReza Sabdar 			}
478*2654012fSReza Sabdar 		}
479*2654012fSReza Sabdar 		if (mode) {
480*2654012fSReza Sabdar 			(*handler->fh_func) (handler->fh_cookie,
481*2654012fSReza Sabdar 			    handler->fh_fd, mode);
482*2654012fSReza Sabdar 
483*2654012fSReza Sabdar 			/*
484*2654012fSReza Sabdar 			 * K.L. The list can be modified during the execution
485*2654012fSReza Sabdar 			 * of handler->fh_func. Therefore, handler will start
486*2654012fSReza Sabdar 			 * from the beginning of the handler list after
487*2654012fSReza Sabdar 			 * each execution.
488*2654012fSReza Sabdar 			 */
489*2654012fSReza Sabdar 			handler = session->ns_file_handler_list;
490*2654012fSReza Sabdar 
491*2654012fSReza Sabdar 			/*
492*2654012fSReza Sabdar 			 * Release the thread which is waiting for a request
493*2654012fSReza Sabdar 			 * to be proccessed.
494*2654012fSReza Sabdar 			 */
495*2654012fSReza Sabdar 			nlp_event_nw(session);
496*2654012fSReza Sabdar 		} else
497*2654012fSReza Sabdar 			handler = handler->fh_next;
498*2654012fSReza Sabdar 
499*2654012fSReza Sabdar 	}
500*2654012fSReza Sabdar 
501*2654012fSReza Sabdar 	nlp_event_rv_set(session, 1);
502*2654012fSReza Sabdar 	return (1);
503*2654012fSReza Sabdar }
504*2654012fSReza Sabdar 
505*2654012fSReza Sabdar 
506*2654012fSReza Sabdar /*
507*2654012fSReza Sabdar  * ndmpd_save_env
508*2654012fSReza Sabdar  *
509*2654012fSReza Sabdar  * Saves a copy of the environment variable list from the data_start_backup
510*2654012fSReza Sabdar  * request or data_start_recover request.
511*2654012fSReza Sabdar  *
512*2654012fSReza Sabdar  * Parameters:
513*2654012fSReza Sabdar  *   session (input) - session pointer.
514*2654012fSReza Sabdar  *   env     (input) - environment variable list to be saved.
515*2654012fSReza Sabdar  *   envlen  (input) - length of variable array.
516*2654012fSReza Sabdar  *
517*2654012fSReza Sabdar  * Returns:
518*2654012fSReza Sabdar  *   error code.
519*2654012fSReza Sabdar  */
520*2654012fSReza Sabdar ndmp_error
521*2654012fSReza Sabdar ndmpd_save_env(ndmpd_session_t *session, ndmp_pval *env, ulong_t envlen)
522*2654012fSReza Sabdar {
523*2654012fSReza Sabdar 	ulong_t i;
524*2654012fSReza Sabdar 	char *namebuf;
525*2654012fSReza Sabdar 	char *valbuf;
526*2654012fSReza Sabdar 
527*2654012fSReza Sabdar 	session->ns_data.dd_env_len = 0;
528*2654012fSReza Sabdar 
529*2654012fSReza Sabdar 	if (envlen == 0)
530*2654012fSReza Sabdar 		return (NDMP_NO_ERR);
531*2654012fSReza Sabdar 
532*2654012fSReza Sabdar 	session->ns_data.dd_env = ndmp_malloc(sizeof (ndmp_pval) * envlen);
533*2654012fSReza Sabdar 	if (session->ns_data.dd_env == 0)
534*2654012fSReza Sabdar 		return (NDMP_NO_MEM_ERR);
535*2654012fSReza Sabdar 
536*2654012fSReza Sabdar 	for (i = 0; i < envlen; i++) {
537*2654012fSReza Sabdar 		namebuf = strdup(env[i].name);
538*2654012fSReza Sabdar 		if (namebuf == 0)
539*2654012fSReza Sabdar 			return (NDMP_NO_MEM_ERR);
540*2654012fSReza Sabdar 
541*2654012fSReza Sabdar 		valbuf = strdup(env[i].value);
542*2654012fSReza Sabdar 		if (valbuf == 0) {
543*2654012fSReza Sabdar 			free(namebuf);
544*2654012fSReza Sabdar 			return (NDMP_NO_MEM_ERR);
545*2654012fSReza Sabdar 		}
546*2654012fSReza Sabdar 
547*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "env(%s): \"%s\"",
548*2654012fSReza Sabdar 		    namebuf, valbuf);
549*2654012fSReza Sabdar 
550*2654012fSReza Sabdar 		(void) mutex_lock(&session->ns_lock);
551*2654012fSReza Sabdar 		session->ns_data.dd_env[i].name = namebuf;
552*2654012fSReza Sabdar 		session->ns_data.dd_env[i].value = valbuf;
553*2654012fSReza Sabdar 		session->ns_data.dd_env_len++;
554*2654012fSReza Sabdar 		(void) mutex_unlock(&session->ns_lock);
555*2654012fSReza Sabdar 	}
556*2654012fSReza Sabdar 
557*2654012fSReza Sabdar 	return (NDMP_NO_ERR);
558*2654012fSReza Sabdar }
559*2654012fSReza Sabdar 
560*2654012fSReza Sabdar 
561*2654012fSReza Sabdar /*
562*2654012fSReza Sabdar  * ndmpd_free_env
563*2654012fSReza Sabdar  *
564*2654012fSReza Sabdar  * Free the previously saved environment variable array.
565*2654012fSReza Sabdar  *
566*2654012fSReza Sabdar  * Parameters:
567*2654012fSReza Sabdar  *   session - NDMP session pointer.
568*2654012fSReza Sabdar  *
569*2654012fSReza Sabdar  * Returns:
570*2654012fSReza Sabdar  *   void.
571*2654012fSReza Sabdar  */
572*2654012fSReza Sabdar void
573*2654012fSReza Sabdar ndmpd_free_env(ndmpd_session_t *session)
574*2654012fSReza Sabdar {
575*2654012fSReza Sabdar 	ulong_t i;
576*2654012fSReza Sabdar 	int count = session->ns_data.dd_env_len;
577*2654012fSReza Sabdar 
578*2654012fSReza Sabdar 	(void) mutex_lock(&session->ns_lock);
579*2654012fSReza Sabdar 	session->ns_data.dd_env_len = 0;
580*2654012fSReza Sabdar 	for (i = 0; i < count; i++) {
581*2654012fSReza Sabdar 		free(session->ns_data.dd_env[i].name);
582*2654012fSReza Sabdar 		free(session->ns_data.dd_env[i].value);
583*2654012fSReza Sabdar 	}
584*2654012fSReza Sabdar 
585*2654012fSReza Sabdar 	free((char *)session->ns_data.dd_env);
586*2654012fSReza Sabdar 	session->ns_data.dd_env = 0;
587*2654012fSReza Sabdar 	(void) mutex_unlock(&session->ns_lock);
588*2654012fSReza Sabdar }
589*2654012fSReza Sabdar 
590*2654012fSReza Sabdar 
591*2654012fSReza Sabdar /*
592*2654012fSReza Sabdar  * ndmpd_save_nlist_v2
593*2654012fSReza Sabdar  *
594*2654012fSReza Sabdar  * Save a copy of list of file names to be restored.
595*2654012fSReza Sabdar  *
596*2654012fSReza Sabdar  * Parameters:
597*2654012fSReza Sabdar  *   nlist    (input) - name list from data_start_recover request.
598*2654012fSReza Sabdar  *   nlistlen (input) - length of name list.
599*2654012fSReza Sabdar  *
600*2654012fSReza Sabdar  * Returns:
601*2654012fSReza Sabdar  *   array of file name pointers.
602*2654012fSReza Sabdar  *
603*2654012fSReza Sabdar  * Notes:
604*2654012fSReza Sabdar  *   free_nlist should be called to free the returned list.
605*2654012fSReza Sabdar  *   A null pointer indicates the end of the list.
606*2654012fSReza Sabdar  */
607*2654012fSReza Sabdar ndmp_error
608*2654012fSReza Sabdar ndmpd_save_nlist_v2(ndmpd_session_t *session, ndmp_name *nlist,
609*2654012fSReza Sabdar     ulong_t nlistlen)
610*2654012fSReza Sabdar {
611*2654012fSReza Sabdar 	ulong_t i;
612*2654012fSReza Sabdar 	char *namebuf;
613*2654012fSReza Sabdar 	char *destbuf;
614*2654012fSReza Sabdar 
615*2654012fSReza Sabdar 	if (nlistlen == 0)
616*2654012fSReza Sabdar 		return (NDMP_NO_ERR);
617*2654012fSReza Sabdar 
618*2654012fSReza Sabdar 	session->ns_data.dd_nlist_len = 0;
619*2654012fSReza Sabdar 	session->ns_data.dd_nlist = ndmp_malloc(sizeof (ndmp_name)*nlistlen);
620*2654012fSReza Sabdar 	if (session->ns_data.dd_nlist == 0)
621*2654012fSReza Sabdar 		return (NDMP_NO_MEM_ERR);
622*2654012fSReza Sabdar 
623*2654012fSReza Sabdar 	for (i = 0; i < nlistlen; i++) {
624*2654012fSReza Sabdar 		namebuf = ndmp_malloc(strlen(nlist[i].name) + 1);
625*2654012fSReza Sabdar 		if (namebuf == 0)
626*2654012fSReza Sabdar 			return (NDMP_NO_MEM_ERR);
627*2654012fSReza Sabdar 
628*2654012fSReza Sabdar 		destbuf = ndmp_malloc(strlen(nlist[i].dest) + 1);
629*2654012fSReza Sabdar 		if (destbuf == 0) {
630*2654012fSReza Sabdar 			free(namebuf);
631*2654012fSReza Sabdar 			return (NDMP_NO_MEM_ERR);
632*2654012fSReza Sabdar 		}
633*2654012fSReza Sabdar 		(void) strlcpy(namebuf, nlist[i].name,
634*2654012fSReza Sabdar 		    strlen(nlist[i].name) + 1);
635*2654012fSReza Sabdar 		(void) strlcpy(destbuf, nlist[i].dest,
636*2654012fSReza Sabdar 		    strlen(nlist[i].dest) + 1);
637*2654012fSReza Sabdar 
638*2654012fSReza Sabdar 		session->ns_data.dd_nlist[i].name = namebuf;
639*2654012fSReza Sabdar 		session->ns_data.dd_nlist[i].dest = destbuf;
640*2654012fSReza Sabdar 		session->ns_data.dd_nlist[i].ssid = nlist[i].ssid;
641*2654012fSReza Sabdar 		session->ns_data.dd_nlist[i].fh_info = nlist[i].fh_info;
642*2654012fSReza Sabdar 		session->ns_data.dd_nlist_len++;
643*2654012fSReza Sabdar 	}
644*2654012fSReza Sabdar 
645*2654012fSReza Sabdar 	return (NDMP_NO_ERR);
646*2654012fSReza Sabdar }
647*2654012fSReza Sabdar 
648*2654012fSReza Sabdar 
649*2654012fSReza Sabdar /*
650*2654012fSReza Sabdar  * ndmpd_free_nlist_v2
651*2654012fSReza Sabdar  *
652*2654012fSReza Sabdar  * Free a list created by ndmpd_save_nlist_v2.
653*2654012fSReza Sabdar  *
654*2654012fSReza Sabdar  * Parameters:
655*2654012fSReza Sabdar  *   session (input) - session pointer.
656*2654012fSReza Sabdar  *
657*2654012fSReza Sabdar  * Returns:
658*2654012fSReza Sabdar  *   void
659*2654012fSReza Sabdar  */
660*2654012fSReza Sabdar void
661*2654012fSReza Sabdar ndmpd_free_nlist_v2(ndmpd_session_t *session)
662*2654012fSReza Sabdar {
663*2654012fSReza Sabdar 	ulong_t i;
664*2654012fSReza Sabdar 
665*2654012fSReza Sabdar 	for (i = 0; i < session->ns_data.dd_nlist_len; i++) {
666*2654012fSReza Sabdar 		free(session->ns_data.dd_nlist[i].name);
667*2654012fSReza Sabdar 		free(session->ns_data.dd_nlist[i].dest);
668*2654012fSReza Sabdar 	}
669*2654012fSReza Sabdar 
670*2654012fSReza Sabdar 	if (session->ns_data.dd_nlist != NULL)
671*2654012fSReza Sabdar 		free((char *)session->ns_data.dd_nlist);
672*2654012fSReza Sabdar 	session->ns_data.dd_nlist = 0;
673*2654012fSReza Sabdar 	session->ns_data.dd_nlist_len = 0;
674*2654012fSReza Sabdar }
675*2654012fSReza Sabdar 
676*2654012fSReza Sabdar 
677*2654012fSReza Sabdar /*
678*2654012fSReza Sabdar  * ndmpd_free_nlist_v3
679*2654012fSReza Sabdar  *
680*2654012fSReza Sabdar  * Free a list created by ndmpd_save_nlist_v3.
681*2654012fSReza Sabdar  *
682*2654012fSReza Sabdar  * Parameters:
683*2654012fSReza Sabdar  *   session (input) - session pointer.
684*2654012fSReza Sabdar  *
685*2654012fSReza Sabdar  * Returns:
686*2654012fSReza Sabdar  *   void
687*2654012fSReza Sabdar  */
688*2654012fSReza Sabdar void
689*2654012fSReza Sabdar ndmpd_free_nlist_v3(ndmpd_session_t *session)
690*2654012fSReza Sabdar {
691*2654012fSReza Sabdar 	ulong_t i;
692*2654012fSReza Sabdar 	mem_ndmp_name_v3_t *tp; /* destination entry */
693*2654012fSReza Sabdar 
694*2654012fSReza Sabdar 	tp = session->ns_data.dd_nlist_v3;
695*2654012fSReza Sabdar 	for (i = 0; i < session->ns_data.dd_nlist_len; tp++, i++) {
696*2654012fSReza Sabdar 		NDMP_FREE(tp->nm3_opath);
697*2654012fSReza Sabdar 		NDMP_FREE(tp->nm3_dpath);
698*2654012fSReza Sabdar 		NDMP_FREE(tp->nm3_newnm);
699*2654012fSReza Sabdar 	}
700*2654012fSReza Sabdar 
701*2654012fSReza Sabdar 	NDMP_FREE(session->ns_data.dd_nlist_v3);
702*2654012fSReza Sabdar 	session->ns_data.dd_nlist_len = 0;
703*2654012fSReza Sabdar }
704*2654012fSReza Sabdar 
705*2654012fSReza Sabdar 
706*2654012fSReza Sabdar /*
707*2654012fSReza Sabdar  * ndmpd_save_nlist_v3
708*2654012fSReza Sabdar  *
709*2654012fSReza Sabdar  * Save a copy of list of file names to be restored.
710*2654012fSReza Sabdar  *
711*2654012fSReza Sabdar  * Parameters:
712*2654012fSReza Sabdar  *   nlist    (input) - name list from data_start_recover request.
713*2654012fSReza Sabdar  *   nlistlen (input) - length of name list.
714*2654012fSReza Sabdar  *
715*2654012fSReza Sabdar  * Returns:
716*2654012fSReza Sabdar  *   array of file name pointers.
717*2654012fSReza Sabdar  *
718*2654012fSReza Sabdar  * Notes:
719*2654012fSReza Sabdar  *   free_nlist should be called to free the returned list.
720*2654012fSReza Sabdar  *   A null pointer indicates the end of the list.
721*2654012fSReza Sabdar  */
722*2654012fSReza Sabdar ndmp_error
723*2654012fSReza Sabdar ndmpd_save_nlist_v3(ndmpd_session_t *session, ndmp_name_v3 *nlist,
724*2654012fSReza Sabdar     ulong_t nlistlen)
725*2654012fSReza Sabdar {
726*2654012fSReza Sabdar 	ulong_t i;
727*2654012fSReza Sabdar 	ndmp_error rv;
728*2654012fSReza Sabdar 	ndmp_name_v3 *sp; /* source entry */
729*2654012fSReza Sabdar 	mem_ndmp_name_v3_t *tp; /* destination entry */
730*2654012fSReza Sabdar 
731*2654012fSReza Sabdar 	if (nlistlen == 0)
732*2654012fSReza Sabdar 		return (NDMP_ILLEGAL_ARGS_ERR);
733*2654012fSReza Sabdar 
734*2654012fSReza Sabdar 	session->ns_data.dd_nlist_len = 0;
735*2654012fSReza Sabdar 	tp = session->ns_data.dd_nlist_v3 =
736*2654012fSReza Sabdar 	    ndmp_malloc(sizeof (mem_ndmp_name_v3_t) * nlistlen);
737*2654012fSReza Sabdar 	if (session->ns_data.dd_nlist_v3 == 0)
738*2654012fSReza Sabdar 		return (NDMP_NO_MEM_ERR);
739*2654012fSReza Sabdar 
740*2654012fSReza Sabdar 	rv = NDMP_NO_ERR;
741*2654012fSReza Sabdar 	sp = nlist;
742*2654012fSReza Sabdar 	for (i = 0; i < nlistlen; tp++, sp++, i++) {
743*2654012fSReza Sabdar 		tp->nm3_opath = strdup(sp->original_path);
744*2654012fSReza Sabdar 		if (!tp->nm3_opath) {
745*2654012fSReza Sabdar 			rv = NDMP_NO_MEM_ERR;
746*2654012fSReza Sabdar 			break;
747*2654012fSReza Sabdar 		}
748*2654012fSReza Sabdar 		if (!*sp->destination_dir) {
749*2654012fSReza Sabdar 			tp->nm3_dpath = NULL;
750*2654012fSReza Sabdar 			/* In V4 destination dir cannot be NULL */
751*2654012fSReza Sabdar 			if (session->ns_protocol_version == NDMPV4) {
752*2654012fSReza Sabdar 				rv = NDMP_ILLEGAL_ARGS_ERR;
753*2654012fSReza Sabdar 				break;
754*2654012fSReza Sabdar 			}
755*2654012fSReza Sabdar 		} else if (!(tp->nm3_dpath = strdup(sp->destination_dir))) {
756*2654012fSReza Sabdar 			rv = NDMP_NO_MEM_ERR;
757*2654012fSReza Sabdar 			break;
758*2654012fSReza Sabdar 		}
759*2654012fSReza Sabdar 		if (!*sp->new_name)
760*2654012fSReza Sabdar 			tp->nm3_newnm = NULL;
761*2654012fSReza Sabdar 		else if (!(tp->nm3_newnm = strdup(sp->new_name))) {
762*2654012fSReza Sabdar 			rv = NDMP_NO_MEM_ERR;
763*2654012fSReza Sabdar 			break;
764*2654012fSReza Sabdar 		}
765*2654012fSReza Sabdar 
766*2654012fSReza Sabdar 		tp->nm3_node = quad_to_long_long(sp->node);
767*2654012fSReza Sabdar 		tp->nm3_fh_info = quad_to_long_long(sp->fh_info);
768*2654012fSReza Sabdar 		tp->nm3_err = NDMP_NO_ERR;
769*2654012fSReza Sabdar 		session->ns_data.dd_nlist_len++;
770*2654012fSReza Sabdar 
771*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "orig \"%s\"", tp->nm3_opath);
772*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "dest \"%s\"", NDMP_SVAL(tp->nm3_dpath));
773*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "name \"%s\"", NDMP_SVAL(tp->nm3_newnm));
774*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "node %lld", tp->nm3_node);
775*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "fh_info %lld", tp->nm3_fh_info);
776*2654012fSReza Sabdar 	}
777*2654012fSReza Sabdar 
778*2654012fSReza Sabdar 	if (rv != NDMP_NO_ERR)
779*2654012fSReza Sabdar 		ndmpd_free_nlist_v3(session);
780*2654012fSReza Sabdar 
781*2654012fSReza Sabdar 	return (rv);
782*2654012fSReza Sabdar }
783*2654012fSReza Sabdar 
784*2654012fSReza Sabdar 
785*2654012fSReza Sabdar /*
786*2654012fSReza Sabdar  * ndmpd_free_nlist
787*2654012fSReza Sabdar  *
788*2654012fSReza Sabdar  * Free the recovery list based on the version
789*2654012fSReza Sabdar  *
790*2654012fSReza Sabdar  * Parameters:
791*2654012fSReza Sabdar  *   session (input) - session pointer.
792*2654012fSReza Sabdar  *
793*2654012fSReza Sabdar  * Returns:
794*2654012fSReza Sabdar  *   void
795*2654012fSReza Sabdar  */
796*2654012fSReza Sabdar void
797*2654012fSReza Sabdar ndmpd_free_nlist(ndmpd_session_t *session)
798*2654012fSReza Sabdar {
799*2654012fSReza Sabdar 	switch (session->ns_protocol_version) {
800*2654012fSReza Sabdar 	case 1:
801*2654012fSReza Sabdar 	case 2:
802*2654012fSReza Sabdar 		ndmpd_free_nlist_v2(session);
803*2654012fSReza Sabdar 		break;
804*2654012fSReza Sabdar 	case 3:
805*2654012fSReza Sabdar 	case 4:
806*2654012fSReza Sabdar 		ndmpd_free_nlist_v3(session);
807*2654012fSReza Sabdar 		break;
808*2654012fSReza Sabdar 
809*2654012fSReza Sabdar 	default:
810*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Unknown version %d",
811*2654012fSReza Sabdar 		    session->ns_protocol_version);
812*2654012fSReza Sabdar 	}
813*2654012fSReza Sabdar }
814*2654012fSReza Sabdar 
815*2654012fSReza Sabdar 
816*2654012fSReza Sabdar /*
817*2654012fSReza Sabdar  * fh_cmpv3
818*2654012fSReza Sabdar  *
819*2654012fSReza Sabdar  * Comparison function used in sorting the Nlist based on their
820*2654012fSReza Sabdar  * file history info (offset of the entry on the tape)
821*2654012fSReza Sabdar  *
822*2654012fSReza Sabdar  * Parameters:
823*2654012fSReza Sabdar  *   p (input) - pointer to P
824*2654012fSReza Sabdar  *   q (input) - pointer to Q
825*2654012fSReza Sabdar  *
826*2654012fSReza Sabdar  * Returns:
827*2654012fSReza Sabdar  *  -1: P < Q
828*2654012fSReza Sabdar  *   0: P = Q
829*2654012fSReza Sabdar  *   1: P > Q
830*2654012fSReza Sabdar  */
831*2654012fSReza Sabdar static int
832*2654012fSReza Sabdar fh_cmpv3(const void *p,
833*2654012fSReza Sabdar 		const void *q)
834*2654012fSReza Sabdar {
835*2654012fSReza Sabdar #define	FH_INFOV3(p)	(((mem_ndmp_name_v3_t *)p)->nm3_fh_info)
836*2654012fSReza Sabdar 
837*2654012fSReza Sabdar 	if (FH_INFOV3(p) < FH_INFOV3(q))
838*2654012fSReza Sabdar 		return (-1);
839*2654012fSReza Sabdar 	else if (FH_INFOV3(p) == FH_INFOV3(q))
840*2654012fSReza Sabdar 		return (0);
841*2654012fSReza Sabdar 	else
842*2654012fSReza Sabdar 		return (1);
843*2654012fSReza Sabdar 
844*2654012fSReza Sabdar #undef FH_INFOV3
845*2654012fSReza Sabdar }
846*2654012fSReza Sabdar 
847*2654012fSReza Sabdar 
848*2654012fSReza Sabdar /*
849*2654012fSReza Sabdar  * ndmp_sort_nlist_v3
850*2654012fSReza Sabdar  *
851*2654012fSReza Sabdar  * Sort the recovery list based on their offset on the tape
852*2654012fSReza Sabdar  *
853*2654012fSReza Sabdar  * Parameters:
854*2654012fSReza Sabdar  *   session (input) - session pointer.
855*2654012fSReza Sabdar  *
856*2654012fSReza Sabdar  * Returns:
857*2654012fSReza Sabdar  *   void
858*2654012fSReza Sabdar  */
859*2654012fSReza Sabdar void
860*2654012fSReza Sabdar ndmp_sort_nlist_v3(ndmpd_session_t *session)
861*2654012fSReza Sabdar {
862*2654012fSReza Sabdar 	if (!session || session->ns_data.dd_nlist_len == 0 ||
863*2654012fSReza Sabdar 	    !session->ns_data.dd_nlist_v3)
864*2654012fSReza Sabdar 		return;
865*2654012fSReza Sabdar 
866*2654012fSReza Sabdar 	(void) qsort(session->ns_data.dd_nlist_v3,
867*2654012fSReza Sabdar 	    session->ns_data.dd_nlist_len,
868*2654012fSReza Sabdar 	    sizeof (mem_ndmp_name_v3_t), fh_cmpv3);
869*2654012fSReza Sabdar }
870*2654012fSReza Sabdar 
871*2654012fSReza Sabdar 
872*2654012fSReza Sabdar /*
873*2654012fSReza Sabdar  * ndmp_send_reply
874*2654012fSReza Sabdar  *
875*2654012fSReza Sabdar  * Send the reply, check for error and print the msg if any error
876*2654012fSReza Sabdar  * occured when sending the reply.
877*2654012fSReza Sabdar  *
878*2654012fSReza Sabdar  *   Parameters:
879*2654012fSReza Sabdar  *     connection (input) - connection pointer.
880*2654012fSReza Sabdar  *
881*2654012fSReza Sabdar  *   Return:
882*2654012fSReza Sabdar  *     void
883*2654012fSReza Sabdar  */
884*2654012fSReza Sabdar void
885*2654012fSReza Sabdar ndmp_send_reply(ndmp_connection_t *connection, void *reply, char *msg)
886*2654012fSReza Sabdar {
887*2654012fSReza Sabdar 	if (ndmp_send_response(connection, NDMP_NO_ERR, reply) < 0)
888*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "%s", msg);
889*2654012fSReza Sabdar }
890*2654012fSReza Sabdar 
891*2654012fSReza Sabdar 
892*2654012fSReza Sabdar /*
893*2654012fSReza Sabdar  * ndmp_mtioctl
894*2654012fSReza Sabdar  *
895*2654012fSReza Sabdar  * Performs numerous filemark operations.
896*2654012fSReza Sabdar  *
897*2654012fSReza Sabdar  * Parameters:
898*2654012fSReza Sabdar  * 	fd - file descriptor of the device
899*2654012fSReza Sabdar  *	cmd - filemark or record command
900*2654012fSReza Sabdar  * 	count - the number of operations to be performed
901*2654012fSReza Sabdar  */
902*2654012fSReza Sabdar int
903*2654012fSReza Sabdar ndmp_mtioctl(int fd, int cmd, int count)
904*2654012fSReza Sabdar {
905*2654012fSReza Sabdar 	struct mtop mp;
906*2654012fSReza Sabdar 
907*2654012fSReza Sabdar 	mp.mt_op = cmd;
908*2654012fSReza Sabdar 	mp.mt_count = count;
909*2654012fSReza Sabdar 	if (ioctl(fd, MTIOCTOP, &mp) < 0) {
910*2654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Failed to send command to tape: %m.");
911*2654012fSReza Sabdar 		return (-1);
912*2654012fSReza Sabdar 	}
913*2654012fSReza Sabdar 
914*2654012fSReza Sabdar 	return (0);
915*2654012fSReza Sabdar }
916*2654012fSReza Sabdar 
917*2654012fSReza Sabdar 
918*2654012fSReza Sabdar /*
919*2654012fSReza Sabdar  * quad_to_long_long
920*2654012fSReza Sabdar  *
921*2654012fSReza Sabdar  * Convert type quad to longlong_t
922*2654012fSReza Sabdar  */
923*2654012fSReza Sabdar u_longlong_t
924*2654012fSReza Sabdar quad_to_long_long(ndmp_u_quad q)
925*2654012fSReza Sabdar {
926*2654012fSReza Sabdar 	u_longlong_t ull;
927*2654012fSReza Sabdar 
928*2654012fSReza Sabdar 	ull = ((u_longlong_t)q.high << 32) + q.low;
929*2654012fSReza Sabdar 	return (ull);
930*2654012fSReza Sabdar }
931*2654012fSReza Sabdar 
932*2654012fSReza Sabdar 
933*2654012fSReza Sabdar /*
934*2654012fSReza Sabdar  * long_long_to_quad
935*2654012fSReza Sabdar  *
936*2654012fSReza Sabdar  * Convert long long to quad type
937*2654012fSReza Sabdar  */
938*2654012fSReza Sabdar ndmp_u_quad
939*2654012fSReza Sabdar long_long_to_quad(u_longlong_t ull)
940*2654012fSReza Sabdar {
941*2654012fSReza Sabdar 	ndmp_u_quad q;
942*2654012fSReza Sabdar 
943*2654012fSReza Sabdar 	q.high = (ulong_t)(ull >> 32);
944*2654012fSReza Sabdar 	q.low = (ulong_t)ull;
945*2654012fSReza Sabdar 	return (q);
946*2654012fSReza Sabdar }
947*2654012fSReza Sabdar 
948*2654012fSReza Sabdar 
949*2654012fSReza Sabdar /*
950*2654012fSReza Sabdar  * ndmp_set_socket_nodelay
951*2654012fSReza Sabdar  *
952*2654012fSReza Sabdar  * Set the TCP socket option to nodelay mode
953*2654012fSReza Sabdar  */
954*2654012fSReza Sabdar void
955*2654012fSReza Sabdar ndmp_set_socket_nodelay(int sock)
956*2654012fSReza Sabdar {
957*2654012fSReza Sabdar 	int flag = 1;
958*2654012fSReza Sabdar 
959*2654012fSReza Sabdar 	(void) setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof (flag));
960*2654012fSReza Sabdar }
961*2654012fSReza Sabdar 
962*2654012fSReza Sabdar 
963*2654012fSReza Sabdar /*
964*2654012fSReza Sabdar  * ndmp_set_socket_snd_buf
965*2654012fSReza Sabdar  *
966*2654012fSReza Sabdar  * Set the socket send buffer size
967*2654012fSReza Sabdar  */
968*2654012fSReza Sabdar void
969*2654012fSReza Sabdar ndmp_set_socket_snd_buf(int sock, int size)
970*2654012fSReza Sabdar {
971*2654012fSReza Sabdar 	if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) < 0)
972*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "SO_SNDBUF failed errno=%d", errno);
973*2654012fSReza Sabdar }
974*2654012fSReza Sabdar 
975*2654012fSReza Sabdar 
976*2654012fSReza Sabdar /*
977*2654012fSReza Sabdar  * ndmp_set_socket_rcv_buf
978*2654012fSReza Sabdar  *
979*2654012fSReza Sabdar  * Set the socket receive buffer size
980*2654012fSReza Sabdar  */
981*2654012fSReza Sabdar void
982*2654012fSReza Sabdar ndmp_set_socket_rcv_buf(int sock, int size)
983*2654012fSReza Sabdar {
984*2654012fSReza Sabdar 	if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size)) < 0)
985*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "SO_RCVBUF failed errno=%d", errno);
986*2654012fSReza Sabdar }
987*2654012fSReza Sabdar 
988*2654012fSReza Sabdar /*
989*2654012fSReza Sabdar  * ndmp_get_max_tok_seq
990*2654012fSReza Sabdar  *
991*2654012fSReza Sabdar  * Get the maximum permitted token sequence for token-based
992*2654012fSReza Sabdar  * backups.
993*2654012fSReza Sabdar  *
994*2654012fSReza Sabdar  * Parameters:
995*2654012fSReza Sabdar  *   void
996*2654012fSReza Sabdar  *
997*2654012fSReza Sabdar  * Returns:
998*2654012fSReza Sabdar  *   ndmp_max_tok_seq
999*2654012fSReza Sabdar  */
1000*2654012fSReza Sabdar int
1001*2654012fSReza Sabdar ndmp_get_max_tok_seq(void)
1002*2654012fSReza Sabdar {
1003*2654012fSReza Sabdar 	return (ndmp_max_tok_seq);
1004*2654012fSReza Sabdar }
1005*2654012fSReza Sabdar 
1006*2654012fSReza Sabdar /*
1007*2654012fSReza Sabdar  * ndmp_buffer_get_size
1008*2654012fSReza Sabdar  *
1009*2654012fSReza Sabdar  * Return the NDMP transfer buffer size
1010*2654012fSReza Sabdar  *
1011*2654012fSReza Sabdar  * Parameters:
1012*2654012fSReza Sabdar  *   session (input) - session pointer.
1013*2654012fSReza Sabdar  *
1014*2654012fSReza Sabdar  * Returns:
1015*2654012fSReza Sabdar  *   buffer size
1016*2654012fSReza Sabdar  */
1017*2654012fSReza Sabdar long
1018*2654012fSReza Sabdar ndmp_buffer_get_size(ndmpd_session_t *session)
1019*2654012fSReza Sabdar {
1020*2654012fSReza Sabdar 	long xfer_size;
1021*2654012fSReza Sabdar 
1022*2654012fSReza Sabdar 	if (session == NULL)
1023*2654012fSReza Sabdar 		return (0);
1024*2654012fSReza Sabdar 
1025*2654012fSReza Sabdar 	if (session->ns_data.dd_mover.addr_type == NDMP_ADDR_TCP) {
1026*2654012fSReza Sabdar 		xfer_size = atoi(ndmpd_get_prop_default(NDMP_MOVER_RECSIZE,
1027*2654012fSReza Sabdar 		    "60"));
1028*2654012fSReza Sabdar 		if (xfer_size > 0)
1029*2654012fSReza Sabdar 			xfer_size *= KILOBYTE;
1030*2654012fSReza Sabdar 		else
1031*2654012fSReza Sabdar 			xfer_size = REMOTE_RECORD_SIZE;
1032*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Remote operation: %d", xfer_size);
1033*2654012fSReza Sabdar 	} else {
1034*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
1035*2654012fSReza Sabdar 		    "Local operation: %lu", session->ns_mover.md_record_size);
1036*2654012fSReza Sabdar 		if ((xfer_size = session->ns_mover.md_record_size) == 0)
1037*2654012fSReza Sabdar 			xfer_size = MAX_RECORD_SIZE;
1038*2654012fSReza Sabdar 	}
1039*2654012fSReza Sabdar 
1040*2654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "xfer_size: %d", xfer_size);
1041*2654012fSReza Sabdar 	return (xfer_size);
1042*2654012fSReza Sabdar }
1043*2654012fSReza Sabdar 
1044*2654012fSReza Sabdar 
1045*2654012fSReza Sabdar /*
1046*2654012fSReza Sabdar  * ndmp_lbr_init
1047*2654012fSReza Sabdar  *
1048*2654012fSReza Sabdar  * Initialize the LBR/NDMP backup parameters
1049*2654012fSReza Sabdar  *
1050*2654012fSReza Sabdar  * Parameters:
1051*2654012fSReza Sabdar  *   session (input) - session pointer.
1052*2654012fSReza Sabdar  *
1053*2654012fSReza Sabdar  * Returns:
1054*2654012fSReza Sabdar  *   0: on success
1055*2654012fSReza Sabdar  *  -1: otherwise
1056*2654012fSReza Sabdar  */
1057*2654012fSReza Sabdar int
1058*2654012fSReza Sabdar ndmp_lbr_init(ndmpd_session_t *session)
1059*2654012fSReza Sabdar {
1060*2654012fSReza Sabdar 	if (session->ns_ndmp_lbr_params != NULL) {
1061*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "ndmp_lbr_params already allocated.");
1062*2654012fSReza Sabdar 		return (0);
1063*2654012fSReza Sabdar 	}
1064*2654012fSReza Sabdar 
1065*2654012fSReza Sabdar 	session->ns_ndmp_lbr_params = ndmp_malloc(sizeof (ndmp_lbr_params_t));
1066*2654012fSReza Sabdar 	if (session->ns_ndmp_lbr_params == NULL)
1067*2654012fSReza Sabdar 		return (-1);
1068*2654012fSReza Sabdar 
1069*2654012fSReza Sabdar 	session->ns_ndmp_lbr_params->nlp_bkmap = -1;
1070*2654012fSReza Sabdar 	session->ns_ndmp_lbr_params->nlp_session = session;
1071*2654012fSReza Sabdar 	(void) cond_init(&session->ns_ndmp_lbr_params->nlp_cv, 0, NULL);
1072*2654012fSReza Sabdar 	(void) mutex_init(&session->ns_lock, 0, NULL);
1073*2654012fSReza Sabdar 	session->ns_nref = 0;
1074*2654012fSReza Sabdar 	return (0);
1075*2654012fSReza Sabdar }
1076*2654012fSReza Sabdar 
1077*2654012fSReza Sabdar 
1078*2654012fSReza Sabdar /*
1079*2654012fSReza Sabdar  * ndmp_lbr_cleanup
1080*2654012fSReza Sabdar  *
1081*2654012fSReza Sabdar  * Deallocate and cleanup all NDMP/LBR parameters
1082*2654012fSReza Sabdar  *
1083*2654012fSReza Sabdar  * Parameters:
1084*2654012fSReza Sabdar  *   session (input) - session pointer.
1085*2654012fSReza Sabdar  *
1086*2654012fSReza Sabdar  * Returns:
1087*2654012fSReza Sabdar  *   0: on success
1088*2654012fSReza Sabdar  *  -1: otherwise
1089*2654012fSReza Sabdar  */
1090*2654012fSReza Sabdar void
1091*2654012fSReza Sabdar ndmp_lbr_cleanup(ndmpd_session_t *session)
1092*2654012fSReza Sabdar {
1093*2654012fSReza Sabdar 	/*
1094*2654012fSReza Sabdar 	 * If in 3-way restore, the connection close is detected after
1095*2654012fSReza Sabdar 	 * check in tape_read(), the reader thread of mover may wait forever
1096*2654012fSReza Sabdar 	 * for the tape to be changed.  Force the reader thread to exit.
1097*2654012fSReza Sabdar 	 */
1098*2654012fSReza Sabdar 	nlp_event_rv_set(session, -2);
1099*2654012fSReza Sabdar 	nlp_event_nw(session);
1100*2654012fSReza Sabdar 
1101*2654012fSReza Sabdar 	ndmpd_abort_marking_v2(session);
1102*2654012fSReza Sabdar 	ndmp_stop_buffer_worker(session);
1103*2654012fSReza Sabdar 	ndmp_waitfor_op(session);
1104*2654012fSReza Sabdar 	ndmp_free_reader_writer_ipc(session);
1105*2654012fSReza Sabdar 	if (session->ns_ndmp_lbr_params) {
1106*2654012fSReza Sabdar 		if (session->ns_ndmp_lbr_params->nlp_bkmap != -1)
1107*2654012fSReza Sabdar 			(void) dbm_free(session->ns_ndmp_lbr_params->nlp_bkmap);
1108*2654012fSReza Sabdar 		tlm_release_list(session->ns_ndmp_lbr_params->nlp_exl);
1109*2654012fSReza Sabdar 		tlm_release_list(session->ns_ndmp_lbr_params->nlp_inc);
1110*2654012fSReza Sabdar 		(void) cond_destroy(&session->ns_ndmp_lbr_params->nlp_cv);
1111*2654012fSReza Sabdar 	}
1112*2654012fSReza Sabdar 
1113*2654012fSReza Sabdar 	NDMP_FREE(session->ns_ndmp_lbr_params);
1114*2654012fSReza Sabdar }
1115*2654012fSReza Sabdar 
1116*2654012fSReza Sabdar 
1117*2654012fSReza Sabdar /*
1118*2654012fSReza Sabdar  * nlp_ref_nw
1119*2654012fSReza Sabdar  *
1120*2654012fSReza Sabdar  * Increase the references to the NDMP/LBR parameter to prevent
1121*2654012fSReza Sabdar  * unwanted release
1122*2654012fSReza Sabdar  *
1123*2654012fSReza Sabdar  * Parameters:
1124*2654012fSReza Sabdar  *   session (input) - session pointer.
1125*2654012fSReza Sabdar  *
1126*2654012fSReza Sabdar  * Returns:
1127*2654012fSReza Sabdar  *   void
1128*2654012fSReza Sabdar  */
1129*2654012fSReza Sabdar void
1130*2654012fSReza Sabdar nlp_ref_nw(ndmpd_session_t *session)
1131*2654012fSReza Sabdar {
1132*2654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
1133*2654012fSReza Sabdar 
1134*2654012fSReza Sabdar 	(void) mutex_lock(&nlp_mtx);
1135*2654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) != NULL) {
1136*2654012fSReza Sabdar 		nlp->nlp_nw++;
1137*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nw: %d", nlp->nlp_nw);
1138*2654012fSReza Sabdar 	} else
1139*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
1140*2654012fSReza Sabdar 	(void) mutex_unlock(&nlp_mtx);
1141*2654012fSReza Sabdar }
1142*2654012fSReza Sabdar 
1143*2654012fSReza Sabdar 
1144*2654012fSReza Sabdar /*
1145*2654012fSReza Sabdar  * nlp_unref_nw
1146*2654012fSReza Sabdar  *
1147*2654012fSReza Sabdar  * Decrease the references to the NDMP/LBR parameter before
1148*2654012fSReza Sabdar  * release
1149*2654012fSReza Sabdar  *
1150*2654012fSReza Sabdar  * Parameters:
1151*2654012fSReza Sabdar  *   session (input) - session pointer.
1152*2654012fSReza Sabdar  *
1153*2654012fSReza Sabdar  * Returns:
1154*2654012fSReza Sabdar  *   void
1155*2654012fSReza Sabdar  */
1156*2654012fSReza Sabdar void
1157*2654012fSReza Sabdar nlp_unref_nw(ndmpd_session_t *session)
1158*2654012fSReza Sabdar {
1159*2654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
1160*2654012fSReza Sabdar 
1161*2654012fSReza Sabdar 	(void) mutex_lock(&nlp_mtx);
1162*2654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) != NULL) {
1163*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nw: %d", nlp->nlp_nw);
1164*2654012fSReza Sabdar 		if (nlp->nlp_nw > 0)
1165*2654012fSReza Sabdar 			nlp->nlp_nw--;
1166*2654012fSReza Sabdar 	} else
1167*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
1168*2654012fSReza Sabdar 	(void) mutex_unlock(&nlp_mtx);
1169*2654012fSReza Sabdar }
1170*2654012fSReza Sabdar 
1171*2654012fSReza Sabdar 
1172*2654012fSReza Sabdar /*
1173*2654012fSReza Sabdar  * nlp_wait_nw
1174*2654012fSReza Sabdar  *
1175*2654012fSReza Sabdar  * Wait for a NDMP/LBR parameter to get available
1176*2654012fSReza Sabdar  *
1177*2654012fSReza Sabdar  * Parameters:
1178*2654012fSReza Sabdar  *   session (input) - session pointer.
1179*2654012fSReza Sabdar  *
1180*2654012fSReza Sabdar  * Returns:
1181*2654012fSReza Sabdar  *   void
1182*2654012fSReza Sabdar  */
1183*2654012fSReza Sabdar void
1184*2654012fSReza Sabdar nlp_wait_nw(ndmpd_session_t *session)
1185*2654012fSReza Sabdar {
1186*2654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
1187*2654012fSReza Sabdar 
1188*2654012fSReza Sabdar 	(void) mutex_lock(&nlp_mtx);
1189*2654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) != NULL) {
1190*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nw: %d", nlp->nlp_nw);
1191*2654012fSReza Sabdar 		if (nlp->nlp_nw > 0) {
1192*2654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "Waiting");
1193*2654012fSReza Sabdar 			while ((nlp->nlp_flag & NLP_READY) == 0)
1194*2654012fSReza Sabdar 				(void) cond_wait(&nlp->nlp_cv, &nlp_mtx);
1195*2654012fSReza Sabdar 		}
1196*2654012fSReza Sabdar 	} else
1197*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
1198*2654012fSReza Sabdar 	(void) mutex_unlock(&nlp_mtx);
1199*2654012fSReza Sabdar }
1200*2654012fSReza Sabdar 
1201*2654012fSReza Sabdar 
1202*2654012fSReza Sabdar /*
1203*2654012fSReza Sabdar  * nlp_event_nw
1204*2654012fSReza Sabdar  *
1205*2654012fSReza Sabdar  * Signal that a NDMP/LBR parameter is available to wake up the
1206*2654012fSReza Sabdar  * threads waiting on that
1207*2654012fSReza Sabdar  *
1208*2654012fSReza Sabdar  * Parameters:
1209*2654012fSReza Sabdar  *   session (input) - session pointer.
1210*2654012fSReza Sabdar  *
1211*2654012fSReza Sabdar  * Returns:
1212*2654012fSReza Sabdar  *   void
1213*2654012fSReza Sabdar  */
1214*2654012fSReza Sabdar void
1215*2654012fSReza Sabdar nlp_event_nw(ndmpd_session_t *session)
1216*2654012fSReza Sabdar {
1217*2654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
1218*2654012fSReza Sabdar 
1219*2654012fSReza Sabdar 	(void) mutex_lock(&nlp_mtx);
1220*2654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) != NULL) {
1221*2654012fSReza Sabdar 		if (nlp->nlp_nw > 0) {
1222*2654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "nw: %d", nlp->nlp_nw);
1223*2654012fSReza Sabdar 			nlp->nlp_flag |= NLP_READY;
1224*2654012fSReza Sabdar 			(void) cond_signal(&nlp->nlp_cv);
1225*2654012fSReza Sabdar 		}
1226*2654012fSReza Sabdar 	} else
1227*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
1228*2654012fSReza Sabdar 	(void) mutex_unlock(&nlp_mtx);
1229*2654012fSReza Sabdar }
1230*2654012fSReza Sabdar 
1231*2654012fSReza Sabdar 
1232*2654012fSReza Sabdar /*
1233*2654012fSReza Sabdar  * nlp_event_rv_get
1234*2654012fSReza Sabdar  *
1235*2654012fSReza Sabdar  * Get the return value for each NLP
1236*2654012fSReza Sabdar  *
1237*2654012fSReza Sabdar  * Parameters:
1238*2654012fSReza Sabdar  *   session (input) - session pointer.
1239*2654012fSReza Sabdar  *
1240*2654012fSReza Sabdar  * Returns:
1241*2654012fSReza Sabdar  *   return value
1242*2654012fSReza Sabdar  */
1243*2654012fSReza Sabdar int
1244*2654012fSReza Sabdar nlp_event_rv_get(ndmpd_session_t *session)
1245*2654012fSReza Sabdar {
1246*2654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
1247*2654012fSReza Sabdar 
1248*2654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
1249*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
1250*2654012fSReza Sabdar 		return (0);
1251*2654012fSReza Sabdar 	}
1252*2654012fSReza Sabdar 
1253*2654012fSReza Sabdar 	return (nlp->nlp_rv);
1254*2654012fSReza Sabdar }
1255*2654012fSReza Sabdar 
1256*2654012fSReza Sabdar 
1257*2654012fSReza Sabdar /*
1258*2654012fSReza Sabdar  * nlp_event_rv_set
1259*2654012fSReza Sabdar  *
1260*2654012fSReza Sabdar  * Set the return value for an NLP
1261*2654012fSReza Sabdar  *
1262*2654012fSReza Sabdar  * Parameters:
1263*2654012fSReza Sabdar  *   session (input) - session pointer.
1264*2654012fSReza Sabdar  *   rv (input) - return value
1265*2654012fSReza Sabdar  *
1266*2654012fSReza Sabdar  * Returns:
1267*2654012fSReza Sabdar  *   void
1268*2654012fSReza Sabdar  */
1269*2654012fSReza Sabdar void
1270*2654012fSReza Sabdar nlp_event_rv_set(ndmpd_session_t *session,
1271*2654012fSReza Sabdar     int rv)
1272*2654012fSReza Sabdar {
1273*2654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
1274*2654012fSReza Sabdar 
1275*2654012fSReza Sabdar 	(void) mutex_lock(&nlp_mtx);
1276*2654012fSReza Sabdar 	if (rv != 0)
1277*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "rv: %d", rv);
1278*2654012fSReza Sabdar 
1279*2654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) != NULL)
1280*2654012fSReza Sabdar 		nlp->nlp_rv = rv;
1281*2654012fSReza Sabdar 	else
1282*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
1283*2654012fSReza Sabdar 	(void) mutex_unlock(&nlp_mtx);
1284*2654012fSReza Sabdar }
1285*2654012fSReza Sabdar 
1286*2654012fSReza Sabdar /*
1287*2654012fSReza Sabdar  * is_buffer_erroneous
1288*2654012fSReza Sabdar  *
1289*2654012fSReza Sabdar  * Run a sanity check on the buffer
1290*2654012fSReza Sabdar  *
1291*2654012fSReza Sabdar  * returns:
1292*2654012fSReza Sabdar  *   TRUE: if the buffer seems to have error
1293*2654012fSReza Sabdar  *   FALSE: if the buffer is full and has valid data.
1294*2654012fSReza Sabdar  */
1295*2654012fSReza Sabdar boolean_t
1296*2654012fSReza Sabdar is_buffer_erroneous(tlm_buffer_t *buf)
1297*2654012fSReza Sabdar {
1298*2654012fSReza Sabdar 	boolean_t rv;
1299*2654012fSReza Sabdar 
1300*2654012fSReza Sabdar 	rv = (buf == NULL || buf->tb_eot || buf->tb_eof ||
1301*2654012fSReza Sabdar 	    buf->tb_errno != 0);
1302*2654012fSReza Sabdar 	if (rv) {
1303*2654012fSReza Sabdar 		if (buf == NULL) {
1304*2654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "buf == NULL");
1305*2654012fSReza Sabdar 		} else {
1306*2654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "eot: %u, eof: %u, errno: %d",
1307*2654012fSReza Sabdar 			    buf->tb_eot, buf->tb_eof, buf->tb_errno);
1308*2654012fSReza Sabdar 		}
1309*2654012fSReza Sabdar 	}
1310*2654012fSReza Sabdar 
1311*2654012fSReza Sabdar 	return (rv);
1312*2654012fSReza Sabdar }
1313*2654012fSReza Sabdar 
1314*2654012fSReza Sabdar /*
1315*2654012fSReza Sabdar  * ndmp_execute_cdb
1316*2654012fSReza Sabdar  *
1317*2654012fSReza Sabdar  * Main SCSI CDB execution program, this is used by message handler
1318*2654012fSReza Sabdar  * for the NDMP tape/SCSI execute CDB requests. This function uses
1319*2654012fSReza Sabdar  * USCSI interface to run the CDB command and sets all the CDB parameters
1320*2654012fSReza Sabdar  * in the SCSI query before calling the USCSI ioctl. The result of the
1321*2654012fSReza Sabdar  * CDB is returned in two places:
1322*2654012fSReza Sabdar  *    cmd.uscsi_status		The status of CDB execution
1323*2654012fSReza Sabdar  *    cmd.uscsi_rqstatus	The status of sense requests
1324*2654012fSReza Sabdar  *    reply.error		The general errno (ioctl)
1325*2654012fSReza Sabdar  *
1326*2654012fSReza Sabdar  * Parameters:
1327*2654012fSReza Sabdar  *   session (input) - session pointer
1328*2654012fSReza Sabdar  *   adapter_name (input) - name of SCSI adapter
1329*2654012fSReza Sabdar  *   sid (input) - SCSI target ID
1330*2654012fSReza Sabdar  *   lun (input) - LUN number
1331*2654012fSReza Sabdar  *   request (input) - NDMP client CDB request
1332*2654012fSReza Sabdar  *
1333*2654012fSReza Sabdar  * Returns:
1334*2654012fSReza Sabdar  *   void
1335*2654012fSReza Sabdar  */
1336*2654012fSReza Sabdar /*ARGSUSED*/
1337*2654012fSReza Sabdar void
1338*2654012fSReza Sabdar ndmp_execute_cdb(ndmpd_session_t *session, char *adapter_name, int sid, int lun,
1339*2654012fSReza Sabdar     ndmp_execute_cdb_request *request)
1340*2654012fSReza Sabdar {
1341*2654012fSReza Sabdar 	ndmp_execute_cdb_reply reply;
1342*2654012fSReza Sabdar 	struct uscsi_cmd cmd;
1343*2654012fSReza Sabdar 	int fd;
1344*2654012fSReza Sabdar 	struct open_list *olp;
1345*2654012fSReza Sabdar 	char rq_buf[255];
1346*2654012fSReza Sabdar 
1347*2654012fSReza Sabdar 	(void) memset((void *)&cmd, 0, sizeof (cmd));
1348*2654012fSReza Sabdar 	(void) memset((void *)&reply, 0, sizeof (reply));
1349*2654012fSReza Sabdar 	(void) memset((void *)rq_buf, 0, sizeof (rq_buf));
1350*2654012fSReza Sabdar 
1351*2654012fSReza Sabdar 	cmd.uscsi_flags = USCSI_RQENABLE;
1352*2654012fSReza Sabdar 	if (request->flags == NDMP_SCSI_DATA_IN) {
1353*2654012fSReza Sabdar 		cmd.uscsi_flags |= USCSI_READ;
1354*2654012fSReza Sabdar 		if ((cmd.uscsi_bufaddr =
1355*2654012fSReza Sabdar 		    ndmp_malloc(request->datain_len)) == 0) {
1356*2654012fSReza Sabdar 			reply.error = NDMP_NO_MEM_ERR;
1357*2654012fSReza Sabdar 			if (ndmp_send_response(session->ns_connection,
1358*2654012fSReza Sabdar 			    NDMP_NO_ERR, (void *)&reply) < 0)
1359*2654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG, "error sending"
1360*2654012fSReza Sabdar 				    " scsi_execute_cdb reply.");
1361*2654012fSReza Sabdar 			return;
1362*2654012fSReza Sabdar 		}
1363*2654012fSReza Sabdar 
1364*2654012fSReza Sabdar 		cmd.uscsi_buflen = request->datain_len;
1365*2654012fSReza Sabdar 		cmd.uscsi_rqlen = sizeof (rq_buf);
1366*2654012fSReza Sabdar 		cmd.uscsi_rqbuf = rq_buf;
1367*2654012fSReza Sabdar 	} else if (request->flags == NDMP_SCSI_DATA_OUT) {
1368*2654012fSReza Sabdar 		cmd.uscsi_flags = USCSI_RQENABLE | USCSI_WRITE;
1369*2654012fSReza Sabdar 		cmd.uscsi_bufaddr = request->dataout.dataout_val;
1370*2654012fSReza Sabdar 		cmd.uscsi_buflen = request->dataout.dataout_len;
1371*2654012fSReza Sabdar 	} else {
1372*2654012fSReza Sabdar 		cmd.uscsi_bufaddr = 0;
1373*2654012fSReza Sabdar 		cmd.uscsi_buflen = 0;
1374*2654012fSReza Sabdar 		cmd.uscsi_rqlen = sizeof (rq_buf);
1375*2654012fSReza Sabdar 		cmd.uscsi_rqbuf = rq_buf;
1376*2654012fSReza Sabdar 	}
1377*2654012fSReza Sabdar 
1378*2654012fSReza Sabdar 	cmd.uscsi_timeout = (request->timeout < 1000) ?
1379*2654012fSReza Sabdar 	    1 : (request->timeout / 1000);
1380*2654012fSReza Sabdar 
1381*2654012fSReza Sabdar 	cmd.uscsi_cdb = (caddr_t)request->cdb.cdb_val;
1382*2654012fSReza Sabdar 	cmd.uscsi_cdblen = request->cdb.cdb_len;
1383*2654012fSReza Sabdar 
1384*2654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "cmd: 0x%x, len: %d, flags: %d, datain_len: %d",
1385*2654012fSReza Sabdar 	    request->cdb.cdb_val[0] & 0xff, request->cdb.cdb_len,
1386*2654012fSReza Sabdar 	    request->flags, request->datain_len);
1387*2654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "dataout_len: %d, timeout: %d",
1388*2654012fSReza Sabdar 	    request->dataout.dataout_len, request->timeout);
1389*2654012fSReza Sabdar 
1390*2654012fSReza Sabdar 	if (request->cdb.cdb_len > 12) {
1391*2654012fSReza Sabdar 		reply.error = NDMP_ILLEGAL_ARGS_ERR;
1392*2654012fSReza Sabdar 		ndmp_send_reply(session->ns_connection, (void *) &reply,
1393*2654012fSReza Sabdar 		    "sending execute_cdb reply");
1394*2654012fSReza Sabdar 		if (request->flags == NDMP_SCSI_DATA_IN)
1395*2654012fSReza Sabdar 			free(cmd.uscsi_bufaddr);
1396*2654012fSReza Sabdar 		return;
1397*2654012fSReza Sabdar 	}
1398*2654012fSReza Sabdar 
1399*2654012fSReza Sabdar 	reply.error = NDMP_NO_ERR;
1400*2654012fSReza Sabdar 
1401*2654012fSReza Sabdar 	if ((olp = ndmp_open_list_find(adapter_name, sid, lun)) != NULL) {
1402*2654012fSReza Sabdar 		fd = olp->ol_fd;
1403*2654012fSReza Sabdar 	} else {
1404*2654012fSReza Sabdar 		reply.error = NDMP_DEV_NOT_OPEN_ERR;
1405*2654012fSReza Sabdar 		ndmp_send_reply(session->ns_connection, (void *) &reply,
1406*2654012fSReza Sabdar 		    "sending execute_cdb reply");
1407*2654012fSReza Sabdar 		if (request->flags == NDMP_SCSI_DATA_IN)
1408*2654012fSReza Sabdar 			free(cmd.uscsi_bufaddr);
1409*2654012fSReza Sabdar 		return;
1410*2654012fSReza Sabdar 	}
1411*2654012fSReza Sabdar 
1412*2654012fSReza Sabdar 	if (ioctl(fd, USCSICMD, &cmd) < 0) {
1413*2654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Failed to send command to device: %m");
1414*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "ioctl(USCSICMD) error: %m");
1415*2654012fSReza Sabdar 		if (cmd.uscsi_status == 0)
1416*2654012fSReza Sabdar 			reply.error = NDMP_IO_ERR;
1417*2654012fSReza Sabdar 	}
1418*2654012fSReza Sabdar 
1419*2654012fSReza Sabdar 	reply.status = cmd.uscsi_status;
1420*2654012fSReza Sabdar 
1421*2654012fSReza Sabdar 	if (request->flags == NDMP_SCSI_DATA_IN) {
1422*2654012fSReza Sabdar 		reply.datain.datain_len = cmd.uscsi_buflen;
1423*2654012fSReza Sabdar 		reply.datain.datain_val = cmd.uscsi_bufaddr;
1424*2654012fSReza Sabdar 	} else {
1425*2654012fSReza Sabdar 		reply.dataout_len = request->dataout.dataout_len;
1426*2654012fSReza Sabdar 	}
1427*2654012fSReza Sabdar 
1428*2654012fSReza Sabdar 	reply.ext_sense.ext_sense_len = cmd.uscsi_rqlen - cmd.uscsi_rqresid;
1429*2654012fSReza Sabdar 	reply.ext_sense.ext_sense_val = rq_buf;
1430*2654012fSReza Sabdar 
1431*2654012fSReza Sabdar 	if (ndmp_send_response(session->ns_connection, NDMP_NO_ERR,
1432*2654012fSReza Sabdar 	    (void *)&reply) < 0)
1433*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Error sending scsi_execute_cdb reply.");
1434*2654012fSReza Sabdar 
1435*2654012fSReza Sabdar 	if (request->flags == NDMP_SCSI_DATA_IN)
1436*2654012fSReza Sabdar 		free(cmd.uscsi_bufaddr);
1437*2654012fSReza Sabdar }
1438*2654012fSReza Sabdar 
1439*2654012fSReza Sabdar 
1440*2654012fSReza Sabdar /*
1441*2654012fSReza Sabdar  * ndmp_stop_local_reader
1442*2654012fSReza Sabdar  *
1443*2654012fSReza Sabdar  * Stops a mover reader thread (for local backup only)
1444*2654012fSReza Sabdar  *
1445*2654012fSReza Sabdar  * Parameters:
1446*2654012fSReza Sabdar  *   session (input) - session pointer
1447*2654012fSReza Sabdar  *   cmds (input) - reader/writer command struct
1448*2654012fSReza Sabdar  *
1449*2654012fSReza Sabdar  * Returns:
1450*2654012fSReza Sabdar  *   void
1451*2654012fSReza Sabdar  */
1452*2654012fSReza Sabdar void
1453*2654012fSReza Sabdar ndmp_stop_local_reader(ndmpd_session_t *session, tlm_commands_t *cmds)
1454*2654012fSReza Sabdar {
1455*2654012fSReza Sabdar 	if (session != NULL) {
1456*2654012fSReza Sabdar 		if (session->ns_data.dd_sock == -1) {
1457*2654012fSReza Sabdar 			/*
1458*2654012fSReza Sabdar 			 * 2-way restore.
1459*2654012fSReza Sabdar 			 */
1460*2654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "2-way restore");
1461*2654012fSReza Sabdar 			if (cmds != NULL && cmds->tcs_reader_count > 0) {
1462*2654012fSReza Sabdar 				nlp_event_rv_set(session, -2);
1463*2654012fSReza Sabdar 				nlp_event_nw(session);
1464*2654012fSReza Sabdar 			}
1465*2654012fSReza Sabdar 		}
1466*2654012fSReza Sabdar 	}
1467*2654012fSReza Sabdar }
1468*2654012fSReza Sabdar 
1469*2654012fSReza Sabdar 
1470*2654012fSReza Sabdar /*
1471*2654012fSReza Sabdar  * Stops a mover reader thread (for remote backup only)
1472*2654012fSReza Sabdar  *
1473*2654012fSReza Sabdar  * Parameters:
1474*2654012fSReza Sabdar  *   session (input) - session pointer
1475*2654012fSReza Sabdar  *   cmds (input) - reader/writer command struct
1476*2654012fSReza Sabdar  *
1477*2654012fSReza Sabdar  * Returns:
1478*2654012fSReza Sabdar  *   void
1479*2654012fSReza Sabdar  */
1480*2654012fSReza Sabdar void
1481*2654012fSReza Sabdar ndmp_stop_remote_reader(ndmpd_session_t *session)
1482*2654012fSReza Sabdar {
1483*2654012fSReza Sabdar 	if (session != NULL) {
1484*2654012fSReza Sabdar 		if (session->ns_data.dd_sock >= 0) {
1485*2654012fSReza Sabdar 			/*
1486*2654012fSReza Sabdar 			 * 3-way restore.
1487*2654012fSReza Sabdar 			 */
1488*2654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG,
1489*2654012fSReza Sabdar 			    "data.sock: %d", session->ns_data.dd_sock);
1490*2654012fSReza Sabdar 			(void) close(session->ns_data.dd_sock);
1491*2654012fSReza Sabdar 			session->ns_data.dd_sock = -1;
1492*2654012fSReza Sabdar 		}
1493*2654012fSReza Sabdar 	}
1494*2654012fSReza Sabdar }
1495*2654012fSReza Sabdar 
1496*2654012fSReza Sabdar 
1497*2654012fSReza Sabdar /*
1498*2654012fSReza Sabdar  * ndmp_wait_for_reader
1499*2654012fSReza Sabdar  *
1500*2654012fSReza Sabdar  * Wait for a reader until get done (busy wait)
1501*2654012fSReza Sabdar  */
1502*2654012fSReza Sabdar void
1503*2654012fSReza Sabdar ndmp_wait_for_reader(tlm_commands_t *cmds)
1504*2654012fSReza Sabdar {
1505*2654012fSReza Sabdar 	if (cmds == NULL) {
1506*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "cmds == NULL");
1507*2654012fSReza Sabdar 	} else {
1508*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
1509*2654012fSReza Sabdar 		    "reader_count: %d", cmds->tcs_reader_count);
1510*2654012fSReza Sabdar 
1511*2654012fSReza Sabdar 		while (cmds->tcs_reader_count > 0)
1512*2654012fSReza Sabdar 			(void) sleep(1);
1513*2654012fSReza Sabdar 	}
1514*2654012fSReza Sabdar }
1515*2654012fSReza Sabdar 
1516*2654012fSReza Sabdar 
1517*2654012fSReza Sabdar /*
1518*2654012fSReza Sabdar  * ndmp_open_list_find
1519*2654012fSReza Sabdar  *
1520*2654012fSReza Sabdar  * Find a specific device in the open list
1521*2654012fSReza Sabdar  *
1522*2654012fSReza Sabdar  * Parameters:
1523*2654012fSReza Sabdar  *   dev (input) - device name
1524*2654012fSReza Sabdar  *   sid (input) - SCSI target ID
1525*2654012fSReza Sabdar  *   lun (input) - LUN number
1526*2654012fSReza Sabdar  *
1527*2654012fSReza Sabdar  * Returns:
1528*2654012fSReza Sabdar  *   pointer to the open list entry
1529*2654012fSReza Sabdar  */
1530*2654012fSReza Sabdar struct open_list *
1531*2654012fSReza Sabdar ndmp_open_list_find(char *dev, int sid, int lun)
1532*2654012fSReza Sabdar {
1533*2654012fSReza Sabdar 	struct ol_head *olhp;
1534*2654012fSReza Sabdar 	struct open_list *olp;
1535*2654012fSReza Sabdar 
1536*2654012fSReza Sabdar 	if (dev == NULL || *dev == '\0') {
1537*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid argument");
1538*2654012fSReza Sabdar 		return (NULL);
1539*2654012fSReza Sabdar 	}
1540*2654012fSReza Sabdar 
1541*2654012fSReza Sabdar 	(void) mutex_lock(&ol_mutex);
1542*2654012fSReza Sabdar 	olhp = &ol_head;
1543*2654012fSReza Sabdar 	for (olp = LIST_FIRST(olhp); olp != NULL; olp = LIST_NEXT(olp, ol_q))
1544*2654012fSReza Sabdar 		if (strcmp(olp->ol_devnm, dev) == 0 && olp->ol_sid == sid &&
1545*2654012fSReza Sabdar 		    olp->ol_lun == lun) {
1546*2654012fSReza Sabdar 			(void) mutex_unlock(&ol_mutex);
1547*2654012fSReza Sabdar 			return (olp);
1548*2654012fSReza Sabdar 		}
1549*2654012fSReza Sabdar 
1550*2654012fSReza Sabdar 	(void) mutex_unlock(&ol_mutex);
1551*2654012fSReza Sabdar 	return (NULL);
1552*2654012fSReza Sabdar }
1553*2654012fSReza Sabdar 
1554*2654012fSReza Sabdar 
1555*2654012fSReza Sabdar /*
1556*2654012fSReza Sabdar  * ndmp_open_list_add
1557*2654012fSReza Sabdar  *
1558*2654012fSReza Sabdar  * Add a specific device to the open list
1559*2654012fSReza Sabdar  *
1560*2654012fSReza Sabdar  * Parameters:
1561*2654012fSReza Sabdar  *   conn (input) - connection pointer
1562*2654012fSReza Sabdar  *   dev (input) - device name
1563*2654012fSReza Sabdar  *   sid (input) - SCSI target ID
1564*2654012fSReza Sabdar  *   lun (input) - LUN number
1565*2654012fSReza Sabdar  *   fd (input) - the device file descriptor
1566*2654012fSReza Sabdar  *
1567*2654012fSReza Sabdar  * Returns:
1568*2654012fSReza Sabdar  *   errno
1569*2654012fSReza Sabdar  */
1570*2654012fSReza Sabdar int
1571*2654012fSReza Sabdar ndmp_open_list_add(ndmp_connection_t *conn, char *dev, int sid, int lun, int fd)
1572*2654012fSReza Sabdar {
1573*2654012fSReza Sabdar 	int err;
1574*2654012fSReza Sabdar 	struct ol_head *olhp;
1575*2654012fSReza Sabdar 	struct open_list *olp;
1576*2654012fSReza Sabdar 
1577*2654012fSReza Sabdar 	if (dev == NULL || *dev == '\0') {
1578*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid argument");
1579*2654012fSReza Sabdar 		return (EINVAL);
1580*2654012fSReza Sabdar 	}
1581*2654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG,
1582*2654012fSReza Sabdar 	    "conn: 0x%08x, dev: %s, sid: %d, lun: %d", conn, dev, sid, lun);
1583*2654012fSReza Sabdar 
1584*2654012fSReza Sabdar 	err = 0;
1585*2654012fSReza Sabdar 	olhp = &ol_head;
1586*2654012fSReza Sabdar 
1587*2654012fSReza Sabdar 	if ((olp = ndmp_open_list_find(dev, sid, lun)) != NULL) {
1588*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "already in list");
1589*2654012fSReza Sabdar 		/*
1590*2654012fSReza Sabdar 		 * The adapter handle can be opened many times by the clients.
1591*2654012fSReza Sabdar 		 * Only when the target is set, we must check and reject the
1592*2654012fSReza Sabdar 		 * open request if the device is already being used by another
1593*2654012fSReza Sabdar 		 * session.
1594*2654012fSReza Sabdar 		 */
1595*2654012fSReza Sabdar 		if (sid == -1)
1596*2654012fSReza Sabdar 			olp->ol_nref++;
1597*2654012fSReza Sabdar 		else
1598*2654012fSReza Sabdar 			err = EBUSY;
1599*2654012fSReza Sabdar 	} else if ((olp = ndmp_malloc(sizeof (struct open_list))) == NULL) {
1600*2654012fSReza Sabdar 		err = ENOMEM;
1601*2654012fSReza Sabdar 	} else if ((olp->ol_devnm = strdup(dev)) == NULL) {
1602*2654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Out of memory.");
1603*2654012fSReza Sabdar 		free(olp);
1604*2654012fSReza Sabdar 		err = ENOMEM;
1605*2654012fSReza Sabdar 	} else {
1606*2654012fSReza Sabdar 		olp->cl_conn = conn;
1607*2654012fSReza Sabdar 		olp->ol_nref = 1;
1608*2654012fSReza Sabdar 		olp->ol_sid = sid;
1609*2654012fSReza Sabdar 		olp->ol_lun = lun;
1610*2654012fSReza Sabdar 		if (fd > 0)
1611*2654012fSReza Sabdar 			olp->ol_fd = fd;
1612*2654012fSReza Sabdar 		else
1613*2654012fSReza Sabdar 			olp->ol_fd = -1;
1614*2654012fSReza Sabdar 		(void) mutex_lock(&ol_mutex);
1615*2654012fSReza Sabdar 		/* LINTED: E_CONSTANT_CONDITION */
1616*2654012fSReza Sabdar 		LIST_INSERT_HEAD(olhp, olp, ol_q);
1617*2654012fSReza Sabdar 		(void) mutex_unlock(&ol_mutex);
1618*2654012fSReza Sabdar 	}
1619*2654012fSReza Sabdar 
1620*2654012fSReza Sabdar 	return (err);
1621*2654012fSReza Sabdar }
1622*2654012fSReza Sabdar 
1623*2654012fSReza Sabdar 
1624*2654012fSReza Sabdar /*
1625*2654012fSReza Sabdar  * ndmp_open_list_del
1626*2654012fSReza Sabdar  *
1627*2654012fSReza Sabdar  * Delete a specific device from the open list
1628*2654012fSReza Sabdar  *
1629*2654012fSReza Sabdar  * Parameters:
1630*2654012fSReza Sabdar  *   dev (input) - device name
1631*2654012fSReza Sabdar  *   sid (input) - SCSI target ID
1632*2654012fSReza Sabdar  *   lun (input) - LUN number
1633*2654012fSReza Sabdar  *
1634*2654012fSReza Sabdar  * Returns:
1635*2654012fSReza Sabdar  *   errno
1636*2654012fSReza Sabdar  */
1637*2654012fSReza Sabdar int
1638*2654012fSReza Sabdar ndmp_open_list_del(char *dev, int sid, int lun)
1639*2654012fSReza Sabdar {
1640*2654012fSReza Sabdar 	struct open_list *olp;
1641*2654012fSReza Sabdar 
1642*2654012fSReza Sabdar 	if (dev == NULL || *dev == '\0') {
1643*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid argument");
1644*2654012fSReza Sabdar 		return (EINVAL);
1645*2654012fSReza Sabdar 	}
1646*2654012fSReza Sabdar 	if ((olp = ndmp_open_list_find(dev, sid, lun)) == NULL) {
1647*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "%s not found", dev);
1648*2654012fSReza Sabdar 		return (ENOENT);
1649*2654012fSReza Sabdar 	}
1650*2654012fSReza Sabdar 
1651*2654012fSReza Sabdar 	(void) mutex_lock(&ol_mutex);
1652*2654012fSReza Sabdar 	if (--olp->ol_nref <= 0) {
1653*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG,
1654*2654012fSReza Sabdar 		    "Removed dev: %s, sid: %d, lun: %d", dev, sid, lun);
1655*2654012fSReza Sabdar 		/* LINTED: E_CONSTANT_CONDITION */
1656*2654012fSReza Sabdar 		LIST_REMOVE(olp, ol_q);
1657*2654012fSReza Sabdar 		free(olp->ol_devnm);
1658*2654012fSReza Sabdar 		free(olp);
1659*2654012fSReza Sabdar 	}
1660*2654012fSReza Sabdar 	(void) mutex_unlock(&ol_mutex);
1661*2654012fSReza Sabdar 
1662*2654012fSReza Sabdar 	return (0);
1663*2654012fSReza Sabdar }
1664*2654012fSReza Sabdar 
1665*2654012fSReza Sabdar 
1666*2654012fSReza Sabdar /*
1667*2654012fSReza Sabdar  * ndmp_open_list_release
1668*2654012fSReza Sabdar  *
1669*2654012fSReza Sabdar  * Close all the resources belonging to this connection.
1670*2654012fSReza Sabdar  *
1671*2654012fSReza Sabdar  * Parameters:
1672*2654012fSReza Sabdar  *    ndmp_connection_t *conn : connection identifier
1673*2654012fSReza Sabdar  *
1674*2654012fSReza Sabdar  * Returns:
1675*2654012fSReza Sabdar  *   void
1676*2654012fSReza Sabdar  */
1677*2654012fSReza Sabdar void
1678*2654012fSReza Sabdar ndmp_open_list_release(ndmp_connection_t *conn)
1679*2654012fSReza Sabdar {
1680*2654012fSReza Sabdar 	struct ol_head *olhp = &ol_head;
1681*2654012fSReza Sabdar 	struct open_list *olp;
1682*2654012fSReza Sabdar 	struct open_list *next;
1683*2654012fSReza Sabdar 
1684*2654012fSReza Sabdar 	(void) mutex_lock(&ol_mutex);
1685*2654012fSReza Sabdar 	olp = LIST_FIRST(olhp);
1686*2654012fSReza Sabdar 	while (olp != NULL) {
1687*2654012fSReza Sabdar 		next = LIST_NEXT(olp, ol_q);
1688*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "olp->conn 0x%08x", olp->cl_conn);
1689*2654012fSReza Sabdar 		if (olp->cl_conn == conn) {
1690*2654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG,
1691*2654012fSReza Sabdar 			    "Removed dev: %s, sid: %d, lun: %d",
1692*2654012fSReza Sabdar 			    olp->ol_devnm, olp->ol_sid, olp->ol_lun);
1693*2654012fSReza Sabdar 			/* LINTED: E_CONSTANT_CONDITION */
1694*2654012fSReza Sabdar 			LIST_REMOVE(olp, ol_q);
1695*2654012fSReza Sabdar 			if (olp->ol_fd > 0)
1696*2654012fSReza Sabdar 				(void) close(olp->ol_fd);
1697*2654012fSReza Sabdar 			free(olp->ol_devnm);
1698*2654012fSReza Sabdar 			free(olp);
1699*2654012fSReza Sabdar 		}
1700*2654012fSReza Sabdar 		olp = next;
1701*2654012fSReza Sabdar 	}
1702*2654012fSReza Sabdar 	(void) mutex_unlock(&ol_mutex);
1703*2654012fSReza Sabdar }
1704*2654012fSReza Sabdar 
1705*2654012fSReza Sabdar 
1706*2654012fSReza Sabdar /*
1707*2654012fSReza Sabdar  * ndmp_stop_buffer_worker
1708*2654012fSReza Sabdar  *
1709*2654012fSReza Sabdar  * Stop all reader and writer threads for a specific buffer.
1710*2654012fSReza Sabdar  *
1711*2654012fSReza Sabdar  * Parameters:
1712*2654012fSReza Sabdar  *   session (input) - session pointer
1713*2654012fSReza Sabdar  *
1714*2654012fSReza Sabdar  * Returns:
1715*2654012fSReza Sabdar  *   void
1716*2654012fSReza Sabdar  */
1717*2654012fSReza Sabdar void
1718*2654012fSReza Sabdar ndmp_stop_buffer_worker(ndmpd_session_t *session)
1719*2654012fSReza Sabdar {
1720*2654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
1721*2654012fSReza Sabdar 	tlm_commands_t *cmds;
1722*2654012fSReza Sabdar 
1723*2654012fSReza Sabdar 	session->ns_tape.td_pos = 0;
1724*2654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
1725*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
1726*2654012fSReza Sabdar 	} else {
1727*2654012fSReza Sabdar 		cmds = &nlp->nlp_cmds;
1728*2654012fSReza Sabdar 		if (cmds->tcs_command == NULL) {
1729*2654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "cmds->tcs_command == NULL");
1730*2654012fSReza Sabdar 		} else {
1731*2654012fSReza Sabdar 			cmds->tcs_reader = cmds->tcs_writer = TLM_ABORT;
1732*2654012fSReza Sabdar 			cmds->tcs_command->tc_reader = TLM_ABORT;
1733*2654012fSReza Sabdar 			cmds->tcs_command->tc_writer = TLM_ABORT;
1734*2654012fSReza Sabdar 			while (cmds->tcs_reader_count > 0 ||
1735*2654012fSReza Sabdar 			    cmds->tcs_writer_count > 0) {
1736*2654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
1737*2654012fSReza Sabdar 				    "trying to stop buffer worker");
1738*2654012fSReza Sabdar 				(void) sleep(1);
1739*2654012fSReza Sabdar 			}
1740*2654012fSReza Sabdar 		}
1741*2654012fSReza Sabdar 	}
1742*2654012fSReza Sabdar }
1743*2654012fSReza Sabdar 
1744*2654012fSReza Sabdar 
1745*2654012fSReza Sabdar /*
1746*2654012fSReza Sabdar  * ndmp_stop_reader_thread
1747*2654012fSReza Sabdar  *
1748*2654012fSReza Sabdar  * Stop only the reader threads of a specific buffer
1749*2654012fSReza Sabdar  *
1750*2654012fSReza Sabdar  * Parameters:
1751*2654012fSReza Sabdar  *   session (input) - session pointer
1752*2654012fSReza Sabdar  *
1753*2654012fSReza Sabdar  * Returns:
1754*2654012fSReza Sabdar  *   void
1755*2654012fSReza Sabdar  */
1756*2654012fSReza Sabdar void
1757*2654012fSReza Sabdar ndmp_stop_reader_thread(ndmpd_session_t *session)
1758*2654012fSReza Sabdar {
1759*2654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
1760*2654012fSReza Sabdar 	tlm_commands_t *cmds;
1761*2654012fSReza Sabdar 
1762*2654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
1763*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
1764*2654012fSReza Sabdar 	} else {
1765*2654012fSReza Sabdar 		cmds = &nlp->nlp_cmds;
1766*2654012fSReza Sabdar 		if (cmds->tcs_command == NULL) {
1767*2654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "cmds->tcs_command == NULL");
1768*2654012fSReza Sabdar 		} else {
1769*2654012fSReza Sabdar 			cmds->tcs_reader = TLM_ABORT;
1770*2654012fSReza Sabdar 			cmds->tcs_command->tc_reader = TLM_ABORT;
1771*2654012fSReza Sabdar 			while (cmds->tcs_reader_count > 0) {
1772*2654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
1773*2654012fSReza Sabdar 				    "trying to stop reader thread");
1774*2654012fSReza Sabdar 				(void) sleep(1);
1775*2654012fSReza Sabdar 			}
1776*2654012fSReza Sabdar 		}
1777*2654012fSReza Sabdar 	}
1778*2654012fSReza Sabdar }
1779*2654012fSReza Sabdar 
1780*2654012fSReza Sabdar 
1781*2654012fSReza Sabdar /*
1782*2654012fSReza Sabdar  * ndmp_stop_reader_thread
1783*2654012fSReza Sabdar  *
1784*2654012fSReza Sabdar  * Stop only the writer threads of a specific buffer
1785*2654012fSReza Sabdar  *
1786*2654012fSReza Sabdar  * Parameters:
1787*2654012fSReza Sabdar  *   session (input) - session pointer
1788*2654012fSReza Sabdar  *
1789*2654012fSReza Sabdar  * Returns:
1790*2654012fSReza Sabdar  *   void
1791*2654012fSReza Sabdar  */
1792*2654012fSReza Sabdar void
1793*2654012fSReza Sabdar ndmp_stop_writer_thread(ndmpd_session_t *session)
1794*2654012fSReza Sabdar {
1795*2654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
1796*2654012fSReza Sabdar 	tlm_commands_t *cmds;
1797*2654012fSReza Sabdar 
1798*2654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) == NULL) {
1799*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp == NULL");
1800*2654012fSReza Sabdar 	} else {
1801*2654012fSReza Sabdar 		cmds = &nlp->nlp_cmds;
1802*2654012fSReza Sabdar 		if (cmds->tcs_command == NULL) {
1803*2654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "cmds->tcs_command == NULL");
1804*2654012fSReza Sabdar 		} else {
1805*2654012fSReza Sabdar 			cmds->tcs_writer = TLM_ABORT;
1806*2654012fSReza Sabdar 			cmds->tcs_command->tc_writer = TLM_ABORT;
1807*2654012fSReza Sabdar 			while (cmds->tcs_writer_count > 0) {
1808*2654012fSReza Sabdar 				NDMP_LOG(LOG_DEBUG,
1809*2654012fSReza Sabdar 				    "trying to stop writer thread");
1810*2654012fSReza Sabdar 				(void) sleep(1);
1811*2654012fSReza Sabdar 			}
1812*2654012fSReza Sabdar 		}
1813*2654012fSReza Sabdar 	}
1814*2654012fSReza Sabdar }
1815*2654012fSReza Sabdar 
1816*2654012fSReza Sabdar 
1817*2654012fSReza Sabdar /*
1818*2654012fSReza Sabdar  * ndmp_free_reader_writer_ipc
1819*2654012fSReza Sabdar  *
1820*2654012fSReza Sabdar  * Free and release the reader/writer buffers and the IPC structure
1821*2654012fSReza Sabdar  * for reader and writer threads.
1822*2654012fSReza Sabdar  *
1823*2654012fSReza Sabdar  * Parameters:
1824*2654012fSReza Sabdar  *   session (input) - session pointer
1825*2654012fSReza Sabdar  *
1826*2654012fSReza Sabdar  * Returns:
1827*2654012fSReza Sabdar  *   void
1828*2654012fSReza Sabdar  */
1829*2654012fSReza Sabdar void
1830*2654012fSReza Sabdar ndmp_free_reader_writer_ipc(ndmpd_session_t *session)
1831*2654012fSReza Sabdar {
1832*2654012fSReza Sabdar 	ndmp_lbr_params_t *nlp;
1833*2654012fSReza Sabdar 	tlm_commands_t *cmds;
1834*2654012fSReza Sabdar 
1835*2654012fSReza Sabdar 	if ((nlp = ndmp_get_nlp(session)) != NULL) {
1836*2654012fSReza Sabdar 		cmds = &nlp->nlp_cmds;
1837*2654012fSReza Sabdar 		if (cmds->tcs_command != NULL) {
1838*2654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "cmds->tcs_command->tc_ref: %d",
1839*2654012fSReza Sabdar 			    cmds->tcs_command->tc_ref);
1840*2654012fSReza Sabdar 			tlm_release_reader_writer_ipc(cmds->tcs_command);
1841*2654012fSReza Sabdar 		}
1842*2654012fSReza Sabdar 	}
1843*2654012fSReza Sabdar }
1844*2654012fSReza Sabdar 
1845*2654012fSReza Sabdar 
1846*2654012fSReza Sabdar /*
1847*2654012fSReza Sabdar  * ndmp_waitfor_op
1848*2654012fSReza Sabdar  *
1849*2654012fSReza Sabdar  * Wait for a session reference count to drop to zero
1850*2654012fSReza Sabdar  *
1851*2654012fSReza Sabdar  * Parameters:
1852*2654012fSReza Sabdar  *   session (input) - session pointer
1853*2654012fSReza Sabdar  *
1854*2654012fSReza Sabdar  * Returns:
1855*2654012fSReza Sabdar  *   void
1856*2654012fSReza Sabdar  */
1857*2654012fSReza Sabdar void
1858*2654012fSReza Sabdar ndmp_waitfor_op(ndmpd_session_t *session)
1859*2654012fSReza Sabdar {
1860*2654012fSReza Sabdar 	if (session != NULL) {
1861*2654012fSReza Sabdar 		while (session->ns_nref > 0) {
1862*2654012fSReza Sabdar 			(void) sleep(1);
1863*2654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG,
1864*2654012fSReza Sabdar 			    "waiting for session nref: %d", session->ns_nref);
1865*2654012fSReza Sabdar 		}
1866*2654012fSReza Sabdar 	}
1867*2654012fSReza Sabdar }
1868*2654012fSReza Sabdar 
1869*2654012fSReza Sabdar 
1870*2654012fSReza Sabdar /*
1871*2654012fSReza Sabdar  * ndmp_session_ref
1872*2654012fSReza Sabdar  *
1873*2654012fSReza Sabdar  * Increment the reference count of the session
1874*2654012fSReza Sabdar  *
1875*2654012fSReza Sabdar  * Parameters:
1876*2654012fSReza Sabdar  *   session (input) - session pointer
1877*2654012fSReza Sabdar  *
1878*2654012fSReza Sabdar  * Returns:
1879*2654012fSReza Sabdar  *   void
1880*2654012fSReza Sabdar  */
1881*2654012fSReza Sabdar void
1882*2654012fSReza Sabdar ndmp_session_ref(ndmpd_session_t *session)
1883*2654012fSReza Sabdar {
1884*2654012fSReza Sabdar 	(void) mutex_lock(&session->ns_lock);
1885*2654012fSReza Sabdar 	session->ns_nref++;
1886*2654012fSReza Sabdar 	(void) mutex_unlock(&session->ns_lock);
1887*2654012fSReza Sabdar }
1888*2654012fSReza Sabdar 
1889*2654012fSReza Sabdar 
1890*2654012fSReza Sabdar /*
1891*2654012fSReza Sabdar  * ndmp_session_unref
1892*2654012fSReza Sabdar  *
1893*2654012fSReza Sabdar  * Decrement the reference count of the session
1894*2654012fSReza Sabdar  *
1895*2654012fSReza Sabdar  * Parameters:
1896*2654012fSReza Sabdar  *   session (input) - session pointer
1897*2654012fSReza Sabdar  *
1898*2654012fSReza Sabdar  * Returns:
1899*2654012fSReza Sabdar  *   void
1900*2654012fSReza Sabdar  */
1901*2654012fSReza Sabdar void
1902*2654012fSReza Sabdar ndmp_session_unref(ndmpd_session_t *session)
1903*2654012fSReza Sabdar {
1904*2654012fSReza Sabdar 	(void) mutex_lock(&session->ns_lock);
1905*2654012fSReza Sabdar 	session->ns_nref--;
1906*2654012fSReza Sabdar 	(void) mutex_unlock(&session->ns_lock);
1907*2654012fSReza Sabdar }
1908*2654012fSReza Sabdar 
1909*2654012fSReza Sabdar 
1910*2654012fSReza Sabdar /*
1911*2654012fSReza Sabdar  * ndmp_addr2str_v3
1912*2654012fSReza Sabdar  *
1913*2654012fSReza Sabdar  * Convert the address type to a string
1914*2654012fSReza Sabdar  *
1915*2654012fSReza Sabdar  * Parameters:
1916*2654012fSReza Sabdar  *   type (input) - address type
1917*2654012fSReza Sabdar  *
1918*2654012fSReza Sabdar  * Returns:
1919*2654012fSReza Sabdar  *   type in string
1920*2654012fSReza Sabdar  */
1921*2654012fSReza Sabdar char *
1922*2654012fSReza Sabdar ndmp_addr2str_v3(ndmp_addr_type type)
1923*2654012fSReza Sabdar {
1924*2654012fSReza Sabdar 	char *rv;
1925*2654012fSReza Sabdar 
1926*2654012fSReza Sabdar 	switch (type) {
1927*2654012fSReza Sabdar 	case NDMP_ADDR_LOCAL:
1928*2654012fSReza Sabdar 		rv = "Local";
1929*2654012fSReza Sabdar 		break;
1930*2654012fSReza Sabdar 	case NDMP_ADDR_TCP:
1931*2654012fSReza Sabdar 		rv = "TCP";
1932*2654012fSReza Sabdar 		break;
1933*2654012fSReza Sabdar 	case NDMP_ADDR_FC:
1934*2654012fSReza Sabdar 		rv = "FC";
1935*2654012fSReza Sabdar 		break;
1936*2654012fSReza Sabdar 	case NDMP_ADDR_IPC:
1937*2654012fSReza Sabdar 		rv = "IPC";
1938*2654012fSReza Sabdar 		break;
1939*2654012fSReza Sabdar 	default:
1940*2654012fSReza Sabdar 		rv = "Unknown";
1941*2654012fSReza Sabdar 	}
1942*2654012fSReza Sabdar 
1943*2654012fSReza Sabdar 	return (rv);
1944*2654012fSReza Sabdar }
1945*2654012fSReza Sabdar 
1946*2654012fSReza Sabdar 
1947*2654012fSReza Sabdar /*
1948*2654012fSReza Sabdar  * ndmp_valid_v3addr_type
1949*2654012fSReza Sabdar  *
1950*2654012fSReza Sabdar  * Make sure that the NDMP address is from any of the
1951*2654012fSReza Sabdar  * valid types
1952*2654012fSReza Sabdar  *
1953*2654012fSReza Sabdar  * Parameters:
1954*2654012fSReza Sabdar  *   type (input) - address type
1955*2654012fSReza Sabdar  *
1956*2654012fSReza Sabdar  * Returns:
1957*2654012fSReza Sabdar  *   1: valid
1958*2654012fSReza Sabdar  *   0: invalid
1959*2654012fSReza Sabdar  */
1960*2654012fSReza Sabdar boolean_t
1961*2654012fSReza Sabdar ndmp_valid_v3addr_type(ndmp_addr_type type)
1962*2654012fSReza Sabdar {
1963*2654012fSReza Sabdar 	boolean_t rv;
1964*2654012fSReza Sabdar 
1965*2654012fSReza Sabdar 	switch (type) {
1966*2654012fSReza Sabdar 	case NDMP_ADDR_LOCAL:
1967*2654012fSReza Sabdar 	case NDMP_ADDR_TCP:
1968*2654012fSReza Sabdar 	case NDMP_ADDR_FC:
1969*2654012fSReza Sabdar 	case NDMP_ADDR_IPC:
1970*2654012fSReza Sabdar 		rv = TRUE;
1971*2654012fSReza Sabdar 		break;
1972*2654012fSReza Sabdar 	default:
1973*2654012fSReza Sabdar 		rv = FALSE;
1974*2654012fSReza Sabdar 	}
1975*2654012fSReza Sabdar 
1976*2654012fSReza Sabdar 	return (rv);
1977*2654012fSReza Sabdar }
1978*2654012fSReza Sabdar 
1979*2654012fSReza Sabdar 
1980*2654012fSReza Sabdar /*
1981*2654012fSReza Sabdar  * ndmp_copy_addr_v3
1982*2654012fSReza Sabdar  *
1983*2654012fSReza Sabdar  * Copy NDMP address from source to destination (V2 and V3 only)
1984*2654012fSReza Sabdar  *
1985*2654012fSReza Sabdar  * Parameters:
1986*2654012fSReza Sabdar  *   dst (ouput) - destination address
1987*2654012fSReza Sabdar  *   src (input) - source address
1988*2654012fSReza Sabdar  *
1989*2654012fSReza Sabdar  * Returns:
1990*2654012fSReza Sabdar  *   void
1991*2654012fSReza Sabdar  */
1992*2654012fSReza Sabdar void
1993*2654012fSReza Sabdar ndmp_copy_addr_v3(ndmp_addr_v3 *dst, ndmp_addr_v3 *src)
1994*2654012fSReza Sabdar {
1995*2654012fSReza Sabdar 	dst->addr_type = src->addr_type;
1996*2654012fSReza Sabdar 	switch (src->addr_type) {
1997*2654012fSReza Sabdar 	case NDMP_ADDR_LOCAL:
1998*2654012fSReza Sabdar 		/* nothing */
1999*2654012fSReza Sabdar 		break;
2000*2654012fSReza Sabdar 	case NDMP_ADDR_TCP:
2001*2654012fSReza Sabdar 		dst->tcp_ip_v3 = htonl(src->tcp_ip_v3);
2002*2654012fSReza Sabdar 		dst->tcp_port_v3 = src->tcp_port_v3;
2003*2654012fSReza Sabdar 		break;
2004*2654012fSReza Sabdar 	case NDMP_ADDR_FC:
2005*2654012fSReza Sabdar 	case NDMP_ADDR_IPC:
2006*2654012fSReza Sabdar 	default:
2007*2654012fSReza Sabdar 		break;
2008*2654012fSReza Sabdar 	}
2009*2654012fSReza Sabdar }
2010*2654012fSReza Sabdar 
2011*2654012fSReza Sabdar 
2012*2654012fSReza Sabdar /*
2013*2654012fSReza Sabdar  * ndmp_copy_addr_v4
2014*2654012fSReza Sabdar  *
2015*2654012fSReza Sabdar  * Copy NDMP address from source to destination. V4 has a extra
2016*2654012fSReza Sabdar  * environment list inside the address too which needs to be copied.
2017*2654012fSReza Sabdar  *
2018*2654012fSReza Sabdar  * Parameters:
2019*2654012fSReza Sabdar  *   dst (ouput) - destination address
2020*2654012fSReza Sabdar  *   src (input) - source address
2021*2654012fSReza Sabdar  *
2022*2654012fSReza Sabdar  * Returns:
2023*2654012fSReza Sabdar  *   void
2024*2654012fSReza Sabdar  */
2025*2654012fSReza Sabdar void
2026*2654012fSReza Sabdar ndmp_copy_addr_v4(ndmp_addr_v4 *dst, ndmp_addr_v4 *src)
2027*2654012fSReza Sabdar {
2028*2654012fSReza Sabdar 	int i;
2029*2654012fSReza Sabdar 
2030*2654012fSReza Sabdar 	dst->addr_type = src->addr_type;
2031*2654012fSReza Sabdar 	dst->tcp_len_v4 = src->tcp_len_v4;
2032*2654012fSReza Sabdar 	switch (src->addr_type) {
2033*2654012fSReza Sabdar 	case NDMP_ADDR_LOCAL:
2034*2654012fSReza Sabdar 		/* nothing */
2035*2654012fSReza Sabdar 		break;
2036*2654012fSReza Sabdar 	case NDMP_ADDR_TCP:
2037*2654012fSReza Sabdar 		dst->tcp_addr_v4 = ndmp_malloc(sizeof (ndmp_tcp_addr_v4) *
2038*2654012fSReza Sabdar 		    src->tcp_len_v4);
2039*2654012fSReza Sabdar 		if (dst->tcp_addr_v4 == 0)
2040*2654012fSReza Sabdar 			return;
2041*2654012fSReza Sabdar 
2042*2654012fSReza Sabdar 		for (i = 0; i < src->tcp_len_v4; i++) {
2043*2654012fSReza Sabdar 			dst->tcp_ip_v4(i) = htonl(src->tcp_ip_v4(i));
2044*2654012fSReza Sabdar 			dst->tcp_port_v4(i) = src->tcp_port_v4(i);
2045*2654012fSReza Sabdar 			dst->tcp_env_v4(i).addr_env_len = 0; /* Solaris */
2046*2654012fSReza Sabdar 			dst->tcp_env_v4(i).addr_env_val = 0; /* Solaris */
2047*2654012fSReza Sabdar 		}
2048*2654012fSReza Sabdar 		break;
2049*2654012fSReza Sabdar 	case NDMP_ADDR_FC:
2050*2654012fSReza Sabdar 	case NDMP_ADDR_IPC:
2051*2654012fSReza Sabdar 	default:
2052*2654012fSReza Sabdar 		break;
2053*2654012fSReza Sabdar 	}
2054*2654012fSReza Sabdar }
2055*2654012fSReza Sabdar 
2056*2654012fSReza Sabdar 
2057*2654012fSReza Sabdar /*
2058*2654012fSReza Sabdar  * ndmp_connect_sock_v3
2059*2654012fSReza Sabdar  *
2060*2654012fSReza Sabdar  * Creates a socket and connects to the specified address/port
2061*2654012fSReza Sabdar  *
2062*2654012fSReza Sabdar  * Parameters:
2063*2654012fSReza Sabdar  *   addr (input) - IP address
2064*2654012fSReza Sabdar  *   port (input) - port number
2065*2654012fSReza Sabdar  *
2066*2654012fSReza Sabdar  * Returns:
2067*2654012fSReza Sabdar  *   0: on success
2068*2654012fSReza Sabdar  *  -1: otherwise
2069*2654012fSReza Sabdar  */
2070*2654012fSReza Sabdar int
2071*2654012fSReza Sabdar ndmp_connect_sock_v3(ulong_t addr, ushort_t port)
2072*2654012fSReza Sabdar {
2073*2654012fSReza Sabdar 	int sock;
2074*2654012fSReza Sabdar 	struct sockaddr_in sin;
2075*2654012fSReza Sabdar 	int flag = 1;
2076*2654012fSReza Sabdar 
2077*2654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "addr %s:%d", inet_ntoa(IN_ADDR(addr)), port);
2078*2654012fSReza Sabdar 
2079*2654012fSReza Sabdar 	sock = socket(AF_INET, SOCK_STREAM, 0);
2080*2654012fSReza Sabdar 	if (sock < 0) {
2081*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Socket error: %m");
2082*2654012fSReza Sabdar 		return (-1);
2083*2654012fSReza Sabdar 	}
2084*2654012fSReza Sabdar 
2085*2654012fSReza Sabdar 	(void) memset((void *) &sin, 0, sizeof (sin));
2086*2654012fSReza Sabdar 	sin.sin_family = AF_INET;
2087*2654012fSReza Sabdar 	sin.sin_addr.s_addr = htonl(addr);
2088*2654012fSReza Sabdar 	sin.sin_port = htons(port);
2089*2654012fSReza Sabdar 	if (connect(sock, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
2090*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Connect error: %m");
2091*2654012fSReza Sabdar 		(void) close(sock);
2092*2654012fSReza Sabdar 		sock = -1;
2093*2654012fSReza Sabdar 	} else {
2094*2654012fSReza Sabdar 		if (ndmp_sbs > 0)
2095*2654012fSReza Sabdar 			ndmp_set_socket_snd_buf(sock, ndmp_sbs*KILOBYTE);
2096*2654012fSReza Sabdar 		if (ndmp_rbs > 0)
2097*2654012fSReza Sabdar 			ndmp_set_socket_rcv_buf(sock, ndmp_rbs*KILOBYTE);
2098*2654012fSReza Sabdar 
2099*2654012fSReza Sabdar 		ndmp_set_socket_nodelay(sock);
2100*2654012fSReza Sabdar 		(void) setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &flag,
2101*2654012fSReza Sabdar 		    sizeof (flag));
2102*2654012fSReza Sabdar 
2103*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "sock %d", sock);
2104*2654012fSReza Sabdar 	}
2105*2654012fSReza Sabdar 
2106*2654012fSReza Sabdar 	return (sock);
2107*2654012fSReza Sabdar }
2108*2654012fSReza Sabdar 
2109*2654012fSReza Sabdar /*
2110*2654012fSReza Sabdar  * ndmp_create_socket
2111*2654012fSReza Sabdar  *
2112*2654012fSReza Sabdar  * Creates a socket for listening for accepting data connections.
2113*2654012fSReza Sabdar  *
2114*2654012fSReza Sabdar  * Parameters:
2115*2654012fSReza Sabdar  *   session (input)  - session pointer.
2116*2654012fSReza Sabdar  *   addr    (output) - location to store address of socket.
2117*2654012fSReza Sabdar  *   port    (output) - location to store port of socket.
2118*2654012fSReza Sabdar  *
2119*2654012fSReza Sabdar  * Returns:
2120*2654012fSReza Sabdar  *   0 - success.
2121*2654012fSReza Sabdar  *  -1 - error.
2122*2654012fSReza Sabdar  */
2123*2654012fSReza Sabdar int
2124*2654012fSReza Sabdar ndmp_create_socket(ulong_t *addr, ushort_t *port)
2125*2654012fSReza Sabdar {
2126*2654012fSReza Sabdar 	char *p;
2127*2654012fSReza Sabdar 	int length;
2128*2654012fSReza Sabdar 	int sd;
2129*2654012fSReza Sabdar 	struct sockaddr_in sin;
2130*2654012fSReza Sabdar 
2131*2654012fSReza Sabdar 	p = ndmpd_get_prop(NDMP_MOVER_NIC);
2132*2654012fSReza Sabdar 
2133*2654012fSReza Sabdar 	if (!p || *p == 0)
2134*2654012fSReza Sabdar 		p = gethostaddr();
2135*2654012fSReza Sabdar 
2136*2654012fSReza Sabdar 	if (!p) {
2137*2654012fSReza Sabdar 		NDMP_LOG(LOG_ERR, "Undetermined network port.");
2138*2654012fSReza Sabdar 		return (-1);
2139*2654012fSReza Sabdar 	}
2140*2654012fSReza Sabdar 
2141*2654012fSReza Sabdar 	*addr = inet_addr(p);
2142*2654012fSReza Sabdar 
2143*2654012fSReza Sabdar 	sd = socket(AF_INET, SOCK_STREAM, 0);
2144*2654012fSReza Sabdar 	if (sd < 0) {
2145*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Socket error: %m");
2146*2654012fSReza Sabdar 		return (-1);
2147*2654012fSReza Sabdar 	}
2148*2654012fSReza Sabdar 	sin.sin_family = AF_INET;
2149*2654012fSReza Sabdar 	sin.sin_addr.s_addr = INADDR_ANY;
2150*2654012fSReza Sabdar 	sin.sin_port = 0;
2151*2654012fSReza Sabdar 	length = sizeof (sin);
2152*2654012fSReza Sabdar 
2153*2654012fSReza Sabdar 	if (bind(sd, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
2154*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Bind error: %m");
2155*2654012fSReza Sabdar 		(void) close(sd);
2156*2654012fSReza Sabdar 		sd = -1;
2157*2654012fSReza Sabdar 	} else if (getsockname(sd, (struct sockaddr *)&sin, &length) < 0) {
2158*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "getsockname error: %m");
2159*2654012fSReza Sabdar 		(void) close(sd);
2160*2654012fSReza Sabdar 		sd = -1;
2161*2654012fSReza Sabdar 	} else if (listen(sd, 5) < 0) {
2162*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Listen error: %m");
2163*2654012fSReza Sabdar 		(void) close(sd);
2164*2654012fSReza Sabdar 		sd = -1;
2165*2654012fSReza Sabdar 	} else
2166*2654012fSReza Sabdar 		*port = sin.sin_port;
2167*2654012fSReza Sabdar 
2168*2654012fSReza Sabdar 	return (sd);
2169*2654012fSReza Sabdar }
2170*2654012fSReza Sabdar 
2171*2654012fSReza Sabdar 
2172*2654012fSReza Sabdar /*
2173*2654012fSReza Sabdar  * cctime
2174*2654012fSReza Sabdar  *
2175*2654012fSReza Sabdar  * Convert the specified time into a string.  It's like
2176*2654012fSReza Sabdar  * ctime(), but:
2177*2654012fSReza Sabdar  *     - chops the trailing '\n' of ctime.
2178*2654012fSReza Sabdar  *     - and returns "the epoch" if time is 0.
2179*2654012fSReza Sabdar  *
2180*2654012fSReza Sabdar  * Returns:
2181*2654012fSReza Sabdar  *     "": invalid argument.
2182*2654012fSReza Sabdar  *     "the epoch": if time is 0.
2183*2654012fSReza Sabdar  *     string format of the time.
2184*2654012fSReza Sabdar  */
2185*2654012fSReza Sabdar char *
2186*2654012fSReza Sabdar cctime(time_t *t)
2187*2654012fSReza Sabdar {
2188*2654012fSReza Sabdar 	char *bp, *cp;
2189*2654012fSReza Sabdar 	char tbuf[BUFSIZ];
2190*2654012fSReza Sabdar 
2191*2654012fSReza Sabdar 	if (!t)
2192*2654012fSReza Sabdar 		return ("");
2193*2654012fSReza Sabdar 
2194*2654012fSReza Sabdar 	if (*t == (time_t)0)
2195*2654012fSReza Sabdar 		return ("the epoch");
2196*2654012fSReza Sabdar 
2197*2654012fSReza Sabdar 	bp = ctime_r(t, tbuf, BUFSIZ);
2198*2654012fSReza Sabdar 	cp = strchr(bp, '\n');
2199*2654012fSReza Sabdar 	if (cp)
2200*2654012fSReza Sabdar 		*cp = '\0';
2201*2654012fSReza Sabdar 
2202*2654012fSReza Sabdar 	return (bp);
2203*2654012fSReza Sabdar }
2204*2654012fSReza Sabdar 
2205*2654012fSReza Sabdar 
2206*2654012fSReza Sabdar /*
2207*2654012fSReza Sabdar  * ndmp_new_job_name
2208*2654012fSReza Sabdar  *
2209*2654012fSReza Sabdar  * Create a job name for each backup/restore to keep track
2210*2654012fSReza Sabdar  *
2211*2654012fSReza Sabdar  * Parameters:
2212*2654012fSReza Sabdar  *   jname (output) - job name
2213*2654012fSReza Sabdar  *
2214*2654012fSReza Sabdar  * Returns:
2215*2654012fSReza Sabdar  *   jname
2216*2654012fSReza Sabdar  */
2217*2654012fSReza Sabdar char *
2218*2654012fSReza Sabdar ndmp_new_job_name(char *jname)
2219*2654012fSReza Sabdar {
2220*2654012fSReza Sabdar 	if (jname != NULL) {
2221*2654012fSReza Sabdar 		(void) snprintf(jname, TLM_MAX_BACKUP_JOB_NAME, "%s%d",
2222*2654012fSReza Sabdar 		    NDMP_RCF_BASENAME, ndmp_job_cnt++);
2223*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "jname: \"%s\"", jname);
2224*2654012fSReza Sabdar 	}
2225*2654012fSReza Sabdar 
2226*2654012fSReza Sabdar 	return (jname);
2227*2654012fSReza Sabdar }
2228*2654012fSReza Sabdar 
2229*2654012fSReza Sabdar 
2230*2654012fSReza Sabdar /*
2231*2654012fSReza Sabdar  * fs_is_valid_logvol
2232*2654012fSReza Sabdar  *
2233*2654012fSReza Sabdar  * Check if the log path exists
2234*2654012fSReza Sabdar  *
2235*2654012fSReza Sabdar  * Parameters:
2236*2654012fSReza Sabdar  *   path (input) - log path
2237*2654012fSReza Sabdar  *
2238*2654012fSReza Sabdar  * Returns:
2239*2654012fSReza Sabdar  *   FALSE: invalid
2240*2654012fSReza Sabdar  *   TRUE: valid
2241*2654012fSReza Sabdar  */
2242*2654012fSReza Sabdar boolean_t
2243*2654012fSReza Sabdar fs_is_valid_logvol(char *path)
2244*2654012fSReza Sabdar {
2245*2654012fSReza Sabdar 	struct stat64 st;
2246*2654012fSReza Sabdar 
2247*2654012fSReza Sabdar 	if (stat64(path, &st) < 0)
2248*2654012fSReza Sabdar 		return (FALSE);
2249*2654012fSReza Sabdar 
2250*2654012fSReza Sabdar 	return (TRUE);
2251*2654012fSReza Sabdar }
2252*2654012fSReza Sabdar 
2253*2654012fSReza Sabdar 
2254*2654012fSReza Sabdar /*
2255*2654012fSReza Sabdar  * ndmpd_mk_temp
2256*2654012fSReza Sabdar  *
2257*2654012fSReza Sabdar  * Make a temporary file using the working directory path and the
2258*2654012fSReza Sabdar  * jobname
2259*2654012fSReza Sabdar  *
2260*2654012fSReza Sabdar  * Parameters:
2261*2654012fSReza Sabdar  *   buf (output) - the temporary file name path
2262*2654012fSReza Sabdar  *
2263*2654012fSReza Sabdar  * Returns:
2264*2654012fSReza Sabdar  *   buf
2265*2654012fSReza Sabdar  */
2266*2654012fSReza Sabdar char *
2267*2654012fSReza Sabdar ndmpd_mk_temp(char *buf)
2268*2654012fSReza Sabdar {
2269*2654012fSReza Sabdar 	char fname[TLM_MAX_BACKUP_JOB_NAME];
2270*2654012fSReza Sabdar 	const char *dir;
2271*2654012fSReza Sabdar 	char *rv;
2272*2654012fSReza Sabdar 
2273*2654012fSReza Sabdar 	if (!buf)
2274*2654012fSReza Sabdar 		return (NULL);
2275*2654012fSReza Sabdar 
2276*2654012fSReza Sabdar 	dir = ndmpd_get_prop(NDMP_DEBUG_PATH);
2277*2654012fSReza Sabdar 	if (dir == 0 || *dir == '\0') {
2278*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "NDMP work path not specified");
2279*2654012fSReza Sabdar 		return (0);
2280*2654012fSReza Sabdar 	}
2281*2654012fSReza Sabdar 
2282*2654012fSReza Sabdar 	if (!fs_is_valid_logvol((char *)dir)) {
2283*2654012fSReza Sabdar 		NDMP_LOG(LOG_ERR,
2284*2654012fSReza Sabdar 		    "Log file path cannot be on system volumes.");
2285*2654012fSReza Sabdar 		return (0);
2286*2654012fSReza Sabdar 	}
2287*2654012fSReza Sabdar 
2288*2654012fSReza Sabdar 	dir += strspn(dir, " \t");
2289*2654012fSReza Sabdar 	if (!*dir) {
2290*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "NDMP work path not specified");
2291*2654012fSReza Sabdar 		return (0);
2292*2654012fSReza Sabdar 	}
2293*2654012fSReza Sabdar 
2294*2654012fSReza Sabdar 	rv = buf;
2295*2654012fSReza Sabdar 	(void) ndmp_new_job_name(fname);
2296*2654012fSReza Sabdar 	(void) tlm_cat_path(buf, (char *)dir, fname);
2297*2654012fSReza Sabdar 
2298*2654012fSReza Sabdar 	return (rv);
2299*2654012fSReza Sabdar }
2300*2654012fSReza Sabdar 
2301*2654012fSReza Sabdar 
2302*2654012fSReza Sabdar /*
2303*2654012fSReza Sabdar  * ndmpd_make_bk_dir_path
2304*2654012fSReza Sabdar  *
2305*2654012fSReza Sabdar  * Make a directory path for temporary files under the NDMP
2306*2654012fSReza Sabdar  * working directory.
2307*2654012fSReza Sabdar  *
2308*2654012fSReza Sabdar  * Parameters:
2309*2654012fSReza Sabdar  *   buf (output) - result path
2310*2654012fSReza Sabdar  *   fname (input) - the file name
2311*2654012fSReza Sabdar  *
2312*2654012fSReza Sabdar  * Returns:
2313*2654012fSReza Sabdar  *   buf
2314*2654012fSReza Sabdar  */
2315*2654012fSReza Sabdar char *
2316*2654012fSReza Sabdar ndmpd_make_bk_dir_path(char *buf, char *fname)
2317*2654012fSReza Sabdar {
2318*2654012fSReza Sabdar 	const char *p;
2319*2654012fSReza Sabdar 	char *name;
2320*2654012fSReza Sabdar 	char path[PATH_MAX];
2321*2654012fSReza Sabdar 
2322*2654012fSReza Sabdar 	if (!buf || !fname || !*fname)
2323*2654012fSReza Sabdar 		return (NULL);
2324*2654012fSReza Sabdar 
2325*2654012fSReza Sabdar 	p = ndmpd_get_prop(NDMP_DEBUG_PATH);
2326*2654012fSReza Sabdar 	if (p == NULL || *p == '\0' || !fs_is_valid_logvol((char *)p)) {
2327*2654012fSReza Sabdar 		return (NULL);
2328*2654012fSReza Sabdar 	}
2329*2654012fSReza Sabdar 
2330*2654012fSReza Sabdar 	(void) strlcpy(path, (char *)p, PATH_MAX);
2331*2654012fSReza Sabdar 	(void) trim_whitespace(path);
2332*2654012fSReza Sabdar 
2333*2654012fSReza Sabdar 	if ((name = strrchr(fname, '/')) == 0)
2334*2654012fSReza Sabdar 		name = fname;
2335*2654012fSReza Sabdar 
2336*2654012fSReza Sabdar 	(void) tlm_cat_path(buf, path, name);
2337*2654012fSReza Sabdar 	return (buf);
2338*2654012fSReza Sabdar }
2339*2654012fSReza Sabdar 
2340*2654012fSReza Sabdar 
2341*2654012fSReza Sabdar /*
2342*2654012fSReza Sabdar  * ndmp_is_chkpnt_root
2343*2654012fSReza Sabdar  *
2344*2654012fSReza Sabdar  * Is this a root checkpoint (snapshot) directory.
2345*2654012fSReza Sabdar  * Note: a temporary function
2346*2654012fSReza Sabdar  */
2347*2654012fSReza Sabdar boolean_t
2348*2654012fSReza Sabdar ndmp_is_chkpnt_root(char *path)
2349*2654012fSReza Sabdar {
2350*2654012fSReza Sabdar 	struct stat64 st;
2351*2654012fSReza Sabdar 
2352*2654012fSReza Sabdar 	if (stat64(path, &st) != 0) {
2353*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Couldn't stat path \"%s\"", path);
2354*2654012fSReza Sabdar 		return (TRUE);
2355*2654012fSReza Sabdar 	}
2356*2654012fSReza Sabdar 	return (FALSE);
2357*2654012fSReza Sabdar }
2358*2654012fSReza Sabdar 
2359*2654012fSReza Sabdar 
2360*2654012fSReza Sabdar /*
2361*2654012fSReza Sabdar  * ndmpd_make_exc_list
2362*2654012fSReza Sabdar  *
2363*2654012fSReza Sabdar  * Make a list of files that should not be backed up.
2364*2654012fSReza Sabdar  *
2365*2654012fSReza Sabdar  * Parameters:
2366*2654012fSReza Sabdar  *   void
2367*2654012fSReza Sabdar  *
2368*2654012fSReza Sabdar  * Returns:
2369*2654012fSReza Sabdar  *   list - array of character strings
2370*2654012fSReza Sabdar  */
2371*2654012fSReza Sabdar char **
2372*2654012fSReza Sabdar ndmpd_make_exc_list(void)
2373*2654012fSReza Sabdar {
2374*2654012fSReza Sabdar 	char *val, **cpp;
2375*2654012fSReza Sabdar 	int i, n;
2376*2654012fSReza Sabdar 
2377*2654012fSReza Sabdar 	n = sizeof (exls);
2378*2654012fSReza Sabdar 	if ((cpp = ndmp_malloc(n)) != NULL) {
2379*2654012fSReza Sabdar 		for (i = 0; exls[i] != NULL; i++)
2380*2654012fSReza Sabdar 			cpp[i] = exls[i];
2381*2654012fSReza Sabdar 
2382*2654012fSReza Sabdar 		/*
2383*2654012fSReza Sabdar 		 * If ndmpd_get_prop returns NULL, the array will be
2384*2654012fSReza Sabdar 		 * null-terminated.
2385*2654012fSReza Sabdar 		 */
2386*2654012fSReza Sabdar 		val = ndmpd_get_prop(NDMP_DEBUG_PATH);
2387*2654012fSReza Sabdar 		cpp[i] = val;
2388*2654012fSReza Sabdar 	}
2389*2654012fSReza Sabdar 
2390*2654012fSReza Sabdar 	return (cpp);
2391*2654012fSReza Sabdar }
2392*2654012fSReza Sabdar 
2393*2654012fSReza Sabdar 
2394*2654012fSReza Sabdar /*
2395*2654012fSReza Sabdar  * ndmp_get_bk_dir_ino
2396*2654012fSReza Sabdar  *
2397*2654012fSReza Sabdar  * Get the inode number of the backup directory
2398*2654012fSReza Sabdar  */
2399*2654012fSReza Sabdar int
2400*2654012fSReza Sabdar ndmp_get_bk_dir_ino(ndmp_lbr_params_t *nlp)
2401*2654012fSReza Sabdar {
2402*2654012fSReza Sabdar 	int rv;
2403*2654012fSReza Sabdar 	struct stat64 st;
2404*2654012fSReza Sabdar 
2405*2654012fSReza Sabdar 	if (stat64(nlp->nlp_backup_path, &st) != 0) {
2406*2654012fSReza Sabdar 		rv = -1;
2407*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Getting inode # of \"%s\"",
2408*2654012fSReza Sabdar 		    nlp->nlp_backup_path);
2409*2654012fSReza Sabdar 	} else {
2410*2654012fSReza Sabdar 		rv = 0;
2411*2654012fSReza Sabdar 		nlp->nlp_bkdirino = st.st_ino;
2412*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "nlp_bkdirino: %lu",
2413*2654012fSReza Sabdar 		    (uint_t)nlp->nlp_bkdirino);
2414*2654012fSReza Sabdar 	}
2415*2654012fSReza Sabdar 
2416*2654012fSReza Sabdar 	return (rv);
2417*2654012fSReza Sabdar }
2418*2654012fSReza Sabdar 
2419*2654012fSReza Sabdar 
2420*2654012fSReza Sabdar /*
2421*2654012fSReza Sabdar  * ndmp_check_utf8magic
2422*2654012fSReza Sabdar  *
2423*2654012fSReza Sabdar  * Check if the magic string for exists in the tar header. This
2424*2654012fSReza Sabdar  * magic string (which also indicates that the file names are in
2425*2654012fSReza Sabdar  * UTF8 format) is used as a crest to indetify our own tapes.
2426*2654012fSReza Sabdar  * This checking is always done before all restores except DAR
2427*2654012fSReza Sabdar  * restores.
2428*2654012fSReza Sabdar  */
2429*2654012fSReza Sabdar boolean_t
2430*2654012fSReza Sabdar ndmp_check_utf8magic(tlm_cmd_t *cmd)
2431*2654012fSReza Sabdar {
2432*2654012fSReza Sabdar 	char *cp;
2433*2654012fSReza Sabdar 	int err, len, actual_size;
2434*2654012fSReza Sabdar 
2435*2654012fSReza Sabdar 	if (cmd == NULL) {
2436*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "cmd == NULL");
2437*2654012fSReza Sabdar 		return (FALSE);
2438*2654012fSReza Sabdar 	}
2439*2654012fSReza Sabdar 	if (cmd->tc_buffers == NULL) {
2440*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "cmd->tc_buffers == NULL");
2441*2654012fSReza Sabdar 		return (FALSE);
2442*2654012fSReza Sabdar 	}
2443*2654012fSReza Sabdar 
2444*2654012fSReza Sabdar 	/* wait until the first buffer gets full. */
2445*2654012fSReza Sabdar 	tlm_buffer_in_buf_wait(cmd->tc_buffers);
2446*2654012fSReza Sabdar 
2447*2654012fSReza Sabdar 	err = actual_size = 0;
2448*2654012fSReza Sabdar 	cp = tlm_get_read_buffer(RECORDSIZE, &err, cmd->tc_buffers,
2449*2654012fSReza Sabdar 	    &actual_size);
2450*2654012fSReza Sabdar 	if (cp == NULL) {
2451*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Can't read from buffers, err: %d", err);
2452*2654012fSReza Sabdar 		return (FALSE);
2453*2654012fSReza Sabdar 	}
2454*2654012fSReza Sabdar 	len = strlen(NDMPUTF8MAGIC);
2455*2654012fSReza Sabdar 	if (actual_size < len) {
2456*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Not enough data in the buffers");
2457*2654012fSReza Sabdar 		return (FALSE);
2458*2654012fSReza Sabdar 	}
2459*2654012fSReza Sabdar 
2460*2654012fSReza Sabdar 	return ((strncmp(cp, NDMPUTF8MAGIC, len) == 0) ? TRUE : FALSE);
2461*2654012fSReza Sabdar }
2462*2654012fSReza Sabdar 
2463*2654012fSReza Sabdar 
2464*2654012fSReza Sabdar /*
2465*2654012fSReza Sabdar  * ndmp_get_cur_bk_time
2466*2654012fSReza Sabdar  *
2467*2654012fSReza Sabdar  * Get the backup checkpoint time.
2468*2654012fSReza Sabdar  */
2469*2654012fSReza Sabdar int
2470*2654012fSReza Sabdar ndmp_get_cur_bk_time(ndmp_lbr_params_t *nlp, time_t *tp, char *jname)
2471*2654012fSReza Sabdar {
2472*2654012fSReza Sabdar 	int err;
2473*2654012fSReza Sabdar 
2474*2654012fSReza Sabdar 	if (!nlp || !nlp->nlp_backup_path || !tp) {
2475*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Invalid argument");
2476*2654012fSReza Sabdar 		return (-1);
2477*2654012fSReza Sabdar 	}
2478*2654012fSReza Sabdar 
2479*2654012fSReza Sabdar 	if (!fs_is_chkpnt_enabled(nlp->nlp_backup_path)) {
2480*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Not a chkpnt volume %s",
2481*2654012fSReza Sabdar 		    nlp->nlp_backup_path);
2482*2654012fSReza Sabdar 		*tp = time(NULL);
2483*2654012fSReza Sabdar 		return (0);
2484*2654012fSReza Sabdar 	}
2485*2654012fSReza Sabdar 
2486*2654012fSReza Sabdar 	err = tlm_get_chkpnt_time(nlp->nlp_backup_path, !NLP_ISCHKPNTED(nlp),
2487*2654012fSReza Sabdar 	    tp, jname);
2488*2654012fSReza Sabdar 	if (err != 0) {
2489*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Can't checkpoint time");
2490*2654012fSReza Sabdar 	} else {
2491*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "%s", cctime(tp));
2492*2654012fSReza Sabdar 	}
2493*2654012fSReza Sabdar 
2494*2654012fSReza Sabdar 	return (err);
2495*2654012fSReza Sabdar }
2496*2654012fSReza Sabdar 
2497*2654012fSReza Sabdar 
2498*2654012fSReza Sabdar /*
2499*2654012fSReza Sabdar  * get_relative_path
2500*2654012fSReza Sabdar  */
2501*2654012fSReza Sabdar char *
2502*2654012fSReza Sabdar ndmp_get_relative_path(char *base, char *fullpath)
2503*2654012fSReza Sabdar {
2504*2654012fSReza Sabdar 	char *p = fullpath;
2505*2654012fSReza Sabdar 
2506*2654012fSReza Sabdar 	if (!base || !*base)
2507*2654012fSReza Sabdar 		return (fullpath);
2508*2654012fSReza Sabdar 
2509*2654012fSReza Sabdar 	while (*base) {
2510*2654012fSReza Sabdar 		if (*base != *p)
2511*2654012fSReza Sabdar 			break;
2512*2654012fSReza Sabdar 		p++; base++;
2513*2654012fSReza Sabdar 	}
2514*2654012fSReza Sabdar 
2515*2654012fSReza Sabdar 	if (*p == '/')
2516*2654012fSReza Sabdar 		p++;
2517*2654012fSReza Sabdar 
2518*2654012fSReza Sabdar 	return ((*base) ? fullpath : p);
2519*2654012fSReza Sabdar }
2520*2654012fSReza Sabdar 
2521*2654012fSReza Sabdar 
2522*2654012fSReza Sabdar /*
2523*2654012fSReza Sabdar  * ndmp_get_nlp
2524*2654012fSReza Sabdar  *
2525*2654012fSReza Sabdar  * Get NDMP local backup parameters
2526*2654012fSReza Sabdar  *
2527*2654012fSReza Sabdar  * Parameter:
2528*2654012fSReza Sabdar  *   session cooke
2529*2654012fSReza Sabdar  *
2530*2654012fSReza Sabdar  * Returns:
2531*2654012fSReza Sabdar  *   LBR structure
2532*2654012fSReza Sabdar  */
2533*2654012fSReza Sabdar ndmp_lbr_params_t *
2534*2654012fSReza Sabdar ndmp_get_nlp(void *cookie)
2535*2654012fSReza Sabdar {
2536*2654012fSReza Sabdar 	if (cookie == NULL)
2537*2654012fSReza Sabdar 		return (NULL);
2538*2654012fSReza Sabdar 
2539*2654012fSReza Sabdar 	return (((ndmpd_session_t *)cookie)->ns_ndmp_lbr_params);
2540*2654012fSReza Sabdar }
2541*2654012fSReza Sabdar 
2542*2654012fSReza Sabdar 
2543*2654012fSReza Sabdar /*
2544*2654012fSReza Sabdar  * is_tape_unit_ready
2545*2654012fSReza Sabdar  *
2546*2654012fSReza Sabdar  * Check if the tape device is ready or not
2547*2654012fSReza Sabdar  */
2548*2654012fSReza Sabdar boolean_t
2549*2654012fSReza Sabdar is_tape_unit_ready(char *adptnm, int dev_id)
2550*2654012fSReza Sabdar {
2551*2654012fSReza Sabdar 	int try;
2552*2654012fSReza Sabdar 	int fd = 0;
2553*2654012fSReza Sabdar 
2554*2654012fSReza Sabdar 	try = TUR_MAX_TRY;
2555*2654012fSReza Sabdar 	if (dev_id == 0)
2556*2654012fSReza Sabdar 		fd = open(adptnm, O_RDONLY | O_NDELAY);
2557*2654012fSReza Sabdar 	else
2558*2654012fSReza Sabdar 		fd = dev_id;
2559*2654012fSReza Sabdar 	do {
2560*2654012fSReza Sabdar 		if (scsi_test_unit_ready(fd) >= 0) {
2561*2654012fSReza Sabdar 			NDMP_LOG(LOG_DEBUG, "Unit is ready");
2562*2654012fSReza Sabdar 
2563*2654012fSReza Sabdar 			if (dev_id == 0)
2564*2654012fSReza Sabdar 				(void) close(fd);
2565*2654012fSReza Sabdar 
2566*2654012fSReza Sabdar 			return (TRUE);
2567*2654012fSReza Sabdar 		}
2568*2654012fSReza Sabdar 
2569*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Unit not ready");
2570*2654012fSReza Sabdar 		(void) usleep(TUR_WAIT);
2571*2654012fSReza Sabdar 
2572*2654012fSReza Sabdar 	} while (--try > 0);
2573*2654012fSReza Sabdar 
2574*2654012fSReza Sabdar 	if (dev_id == 0)
2575*2654012fSReza Sabdar 		(void) close(fd);
2576*2654012fSReza Sabdar 
2577*2654012fSReza Sabdar 	NDMP_LOG(LOG_DEBUG, "Unit didn't get ready");
2578*2654012fSReza Sabdar 	return (FALSE);
2579*2654012fSReza Sabdar }
2580*2654012fSReza Sabdar 
2581*2654012fSReza Sabdar 
2582*2654012fSReza Sabdar /*
2583*2654012fSReza Sabdar  * scsi_test_unit_ready
2584*2654012fSReza Sabdar  *
2585*2654012fSReza Sabdar  * This is for Test Unit Read, without this function, the only
2586*2654012fSReza Sabdar  * impact is getting EBUSY's before each operation which we have
2587*2654012fSReza Sabdar  * busy waiting loops checking EBUSY error code.
2588*2654012fSReza Sabdar  */
2589*2654012fSReza Sabdar static int
2590*2654012fSReza Sabdar scsi_test_unit_ready(int dev_id)
2591*2654012fSReza Sabdar {
2592*2654012fSReza Sabdar 	struct uscsi_cmd ucmd;
2593*2654012fSReza Sabdar 	union scsi_cdb cdb;
2594*2654012fSReza Sabdar 	int retval;
2595*2654012fSReza Sabdar 
2596*2654012fSReza Sabdar 	(void) memset(&ucmd, 0, sizeof (struct uscsi_cmd));
2597*2654012fSReza Sabdar 	(void) memset(&cdb, 0, sizeof (union scsi_cdb));
2598*2654012fSReza Sabdar 	cdb.scc_cmd = SCMD_TEST_UNIT_READY;
2599*2654012fSReza Sabdar 	ucmd.uscsi_cdb = (caddr_t)&cdb;
2600*2654012fSReza Sabdar 	ucmd.uscsi_cdblen = CDB_GROUP0;
2601*2654012fSReza Sabdar 	ucmd.uscsi_flags |= USCSI_SILENT;
2602*2654012fSReza Sabdar 
2603*2654012fSReza Sabdar 	retval = ioctl(dev_id, USCSICMD, &ucmd);
2604*2654012fSReza Sabdar 
2605*2654012fSReza Sabdar 	if (retval != 0 && errno != EIO) {
2606*2654012fSReza Sabdar 		NDMP_LOG(LOG_ERR,
2607*2654012fSReza Sabdar 		    "Failed to send inquiry request to device: %m.");
2608*2654012fSReza Sabdar 		NDMP_LOG(LOG_DEBUG, "Inquiry request failed for"
2609*2654012fSReza Sabdar 		    " dev_id:%d err=%d -%m", dev_id, errno);
2610*2654012fSReza Sabdar 		retval = -errno;
2611*2654012fSReza Sabdar 	} else
2612*2654012fSReza Sabdar 		retval = -(ucmd.uscsi_status);
2613*2654012fSReza Sabdar 
2614*2654012fSReza Sabdar 	return (retval);
2615*2654012fSReza Sabdar }
2616*2654012fSReza Sabdar 
2617*2654012fSReza Sabdar 
2618*2654012fSReza Sabdar /*
2619*2654012fSReza Sabdar  * ndmp_load_params
2620*2654012fSReza Sabdar  *
2621*2654012fSReza Sabdar  * Load the parameters.
2622*2654012fSReza Sabdar  *
2623*2654012fSReza Sabdar  * Parameter:
2624*2654012fSReza Sabdar  *   void
2625*2654012fSReza Sabdar  *
2626*2654012fSReza Sabdar  * Returns:
2627*2654012fSReza Sabdar  *   void
2628*2654012fSReza Sabdar  */
2629*2654012fSReza Sabdar void
2630*2654012fSReza Sabdar ndmp_load_params(void)
2631*2654012fSReza Sabdar {
2632*2654012fSReza Sabdar 	struct stat64 st;
2633*2654012fSReza Sabdar 
2634*2654012fSReza Sabdar 	ndmp_dump_path_node = ndmpd_get_prop_yorn(NDMP_DUMP_PATHNODE_ENV) ?
2635*2654012fSReza Sabdar 	    TRUE : FALSE;
2636*2654012fSReza Sabdar 	ndmp_tar_path_node = ndmpd_get_prop_yorn(NDMP_TAR_PATHNODE_ENV) ?
2637*2654012fSReza Sabdar 	    TRUE : FALSE;
2638*2654012fSReza Sabdar 	ndmp_ignore_ctime =
2639*2654012fSReza Sabdar 	    ndmpd_get_prop_yorn(NDMP_IGNCTIME_ENV) ? TRUE : FALSE;
2640*2654012fSReza Sabdar 	ndmp_include_lmtime = ndmpd_get_prop_yorn(NDMP_INCLMTIME_ENV) ?
2641*2654012fSReza Sabdar 	    TRUE : FALSE;
2642*2654012fSReza Sabdar 	ndmp_max_tok_seq = atoi(ndmpd_get_prop_default(NDMP_MAXSEQ_ENV, "9"));
2643*2654012fSReza Sabdar 
2644*2654012fSReza Sabdar 	ndmp_full_restore_path = ndmpd_get_prop_yorn(NDMP_FULL_RESTORE_PATH) ?
2645*2654012fSReza Sabdar 	    TRUE : FALSE;
2646*2654012fSReza Sabdar 
2647*2654012fSReza Sabdar 	ndmp_fhinode = ndmpd_get_prop_yorn(NDMP_FHIST_INCR_ENV) ? TRUE : FALSE;
2648*2654012fSReza Sabdar 
2649*2654012fSReza Sabdar 	/* Get the value from ndmp SMF property. */
2650*2654012fSReza Sabdar 	ndmp_dar_support = ndmpd_get_prop_yorn(NDMP_DAR_SUPPORT);
2651*2654012fSReza Sabdar 
2652*2654012fSReza Sabdar 	ndmp_log_path = ndmpd_get_prop(NDMP_DEBUG_PATH);
2653*2654012fSReza Sabdar 	if ((ndmp_log_path == NULL) || (*ndmp_log_path == NULL))
2654*2654012fSReza Sabdar 		ndmp_log_path = "/var/ndmp";
2655*2654012fSReza Sabdar 
2656*2654012fSReza Sabdar 	if (lstat64(ndmp_log_path, &st) < 0) {
2657*2654012fSReza Sabdar 		if (mkdirp(ndmp_log_path, 0755) < 0)
2658*2654012fSReza Sabdar 			NDMP_LOG(LOG_ERR, "Could not create log path %s: %m.",
2659*2654012fSReza Sabdar 			    ndmp_log_path);
2660*2654012fSReza Sabdar 	}
2661*2654012fSReza Sabdar 
2662*2654012fSReza Sabdar 	if ((ndmp_ver = atoi(ndmpd_get_prop(NDMP_VERSION_ENV))) == 0)
2663*2654012fSReza Sabdar 		ndmp_ver = NDMPVER;
2664*2654012fSReza Sabdar }
2665*2654012fSReza Sabdar 
2666*2654012fSReza Sabdar /*
2667*2654012fSReza Sabdar  * randomize
2668*2654012fSReza Sabdar  *
2669*2654012fSReza Sabdar  * Randomize the contents of a buffer
2670*2654012fSReza Sabdar  *
2671*2654012fSReza Sabdar  * Parameter:
2672*2654012fSReza Sabdar  *   buffer (output) - destination buffer
2673*2654012fSReza Sabdar  *   size (input) - buffer size
2674*2654012fSReza Sabdar  *
2675*2654012fSReza Sabdar  * Returns:
2676*2654012fSReza Sabdar  *   void
2677*2654012fSReza Sabdar  */
2678*2654012fSReza Sabdar void
2679*2654012fSReza Sabdar randomize(unsigned char *buffer, int size)
2680*2654012fSReza Sabdar {
2681*2654012fSReza Sabdar 	/* LINTED improper alignment */
2682*2654012fSReza Sabdar 	unsigned int *p = (unsigned int *)buffer;
2683*2654012fSReza Sabdar 	unsigned int dwlen = size / sizeof (unsigned int);
2684*2654012fSReza Sabdar 	unsigned int remlen = size % sizeof (unsigned int);
2685*2654012fSReza Sabdar 	unsigned int tmp;
2686*2654012fSReza Sabdar 	unsigned int i;
2687*2654012fSReza Sabdar 
2688*2654012fSReza Sabdar 	for (i = 0; i < dwlen; i++)
2689*2654012fSReza Sabdar 		*p++ = random();
2690*2654012fSReza Sabdar 
2691*2654012fSReza Sabdar 	if (remlen) {
2692*2654012fSReza Sabdar 		tmp = random();
2693*2654012fSReza Sabdar 		(void) memcpy(p, &tmp, remlen);
2694*2654012fSReza Sabdar 	}
2695*2654012fSReza Sabdar }
2696*2654012fSReza Sabdar 
2697*2654012fSReza Sabdar /*
2698*2654012fSReza Sabdar  * ndmpd_get_file_entry_type
2699*2654012fSReza Sabdar  *
2700*2654012fSReza Sabdar  * Converts the mode to the NDMP file type
2701*2654012fSReza Sabdar  *
2702*2654012fSReza Sabdar  * Parameter:
2703*2654012fSReza Sabdar  *   mode (input) - file mode
2704*2654012fSReza Sabdar  *   ftype (output) - file type
2705*2654012fSReza Sabdar  *
2706*2654012fSReza Sabdar  * Returns:
2707*2654012fSReza Sabdar  *   void
2708*2654012fSReza Sabdar  */
2709*2654012fSReza Sabdar void
2710*2654012fSReza Sabdar ndmpd_get_file_entry_type(int mode, ndmp_file_type *ftype)
2711*2654012fSReza Sabdar {
2712*2654012fSReza Sabdar 	switch (mode & S_IFMT) {
2713*2654012fSReza Sabdar 	case S_IFIFO:
2714*2654012fSReza Sabdar 		*ftype = NDMP_FILE_FIFO;
2715*2654012fSReza Sabdar 		break;
2716*2654012fSReza Sabdar 	case S_IFCHR:
2717*2654012fSReza Sabdar 		*ftype = NDMP_FILE_CSPEC;
2718*2654012fSReza Sabdar 		break;
2719*2654012fSReza Sabdar 	case S_IFDIR:
2720*2654012fSReza Sabdar 		*ftype = NDMP_FILE_DIR;
2721*2654012fSReza Sabdar 		break;
2722*2654012fSReza Sabdar 	case S_IFBLK:
2723*2654012fSReza Sabdar 		*ftype = NDMP_FILE_BSPEC;
2724*2654012fSReza Sabdar 		break;
2725*2654012fSReza Sabdar 	case S_IFREG:
2726*2654012fSReza Sabdar 		*ftype = NDMP_FILE_REG;
2727*2654012fSReza Sabdar 		break;
2728*2654012fSReza Sabdar 	case S_IFLNK:
2729*2654012fSReza Sabdar 		*ftype = NDMP_FILE_SLINK;
2730*2654012fSReza Sabdar 		break;
2731*2654012fSReza Sabdar 	default:
2732*2654012fSReza Sabdar 		*ftype = NDMP_FILE_SOCK;
2733*2654012fSReza Sabdar 		break;
2734*2654012fSReza Sabdar 	}
2735*2654012fSReza Sabdar }
2736*2654012fSReza Sabdar 
2737*2654012fSReza Sabdar /*
2738*2654012fSReza Sabdar  * Set a private data in the plugin context
2739*2654012fSReza Sabdar  */
2740*2654012fSReza Sabdar void
2741*2654012fSReza Sabdar ndmp_context_set_specific(ndmp_context_t *nctx, void *ptr)
2742*2654012fSReza Sabdar {
2743*2654012fSReza Sabdar 	nctx->nc_pldata = ptr;
2744*2654012fSReza Sabdar }
2745*2654012fSReza Sabdar 
2746*2654012fSReza Sabdar /*
2747*2654012fSReza Sabdar  * Get a private data in the plugin context
2748*2654012fSReza Sabdar  */
2749*2654012fSReza Sabdar void *
2750*2654012fSReza Sabdar ndmp_context_get_specific(ndmp_context_t *nctx)
2751*2654012fSReza Sabdar {
2752*2654012fSReza Sabdar 	return (nctx->nc_pldata);
2753*2654012fSReza Sabdar }
2754