2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
9 * Copyright (c) 2007, The Storage Networking Industry Association.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * - Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * - Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
22 * - Neither the name of The Storage Networking Industry Association (SNIA)
23 * nor the names of its contributors may be used to endorse or promote
24 * products derived from this software without specific prior written
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
46 #include <ndmpd_door.h>
49 static int ndmp_door_fildes
= -1;
51 static ndmp_door_ctx_t
*dec_ctx
;
52 static ndmp_door_ctx_t
*enc_ctx
;
53 static door_arg_t arg
;
54 static mutex_t ndmp_lock
= DEFAULTMUTEX
;
56 static int ndmp_door_setup(int opcode
);
57 static int ndmp_door_call(void);
58 static int ndmp_door_fini(void);
60 /* ndmp library APIs */
62 ndmp_get_devinfo(ndmp_devinfo_t
**dip
, size_t *size
)
64 ndmp_devinfo_t
*dipptr
;
66 int opcode
= NDMP_DEVICES_GET_INFO
;
68 (void) mutex_lock(&ndmp_lock
);
69 if (ndmp_door_setup(opcode
))
75 /* get the number of devices available */
76 *size
= ndmp_door_get_uint32(dec_ctx
);
78 *dip
= malloc(sizeof (ndmp_devinfo_t
) * *size
);
81 ndmp_errno
= ENDMP_MEM_ALLOC
;
85 for (i
= 0; i
< *size
; i
++, dipptr
++) {
86 dipptr
->nd_dev_type
= ndmp_door_get_int32(dec_ctx
);
87 dipptr
->nd_name
= ndmp_door_get_string(dec_ctx
);
88 dipptr
->nd_lun
= ndmp_door_get_int32(dec_ctx
);
89 dipptr
->nd_sid
= ndmp_door_get_int32(dec_ctx
);
90 dipptr
->nd_vendor
= ndmp_door_get_string(dec_ctx
);
91 dipptr
->nd_product
= ndmp_door_get_string(dec_ctx
);
92 dipptr
->nd_revision
= ndmp_door_get_string(dec_ctx
);
93 dipptr
->nd_serial
= ndmp_door_get_string(dec_ctx
);
94 dipptr
->nd_wwn
= ndmp_door_get_string(dec_ctx
);
96 if (ndmp_door_fini()) {
100 (void) mutex_unlock(&ndmp_lock
);
103 (void) mutex_unlock(&ndmp_lock
);
108 ndmp_get_devinfo_free(ndmp_devinfo_t
*dip
, size_t size
)
110 ndmp_devinfo_t
*dipptr
;
114 for (i
= 0; i
< size
; i
++, dipptr
++) {
115 free(dipptr
->nd_name
);
116 free(dipptr
->nd_vendor
);
117 free(dipptr
->nd_product
);
118 free(dipptr
->nd_revision
);
124 ndmp_terminate_session(int session
)
127 int opcode
= NDMP_TERMINATE_SESSION_ID
;
129 (void) mutex_lock(&ndmp_lock
);
130 if (ndmp_door_setup(opcode
))
133 ndmp_door_put_uint32(enc_ctx
, session
);
134 if (ndmp_door_call())
137 ret
= ndmp_door_get_uint32(dec_ctx
);
138 if (ndmp_door_fini())
141 (void) mutex_unlock(&ndmp_lock
);
144 (void) mutex_unlock(&ndmp_lock
);
149 ndmp_get_session_info(ndmp_session_info_t
**sinfo
, size_t *size
)
153 ndmp_session_info_t
*sp
;
156 ndmp_dt_name_v3_t
*npv3
;
157 int opcode
= NDMP_SHOW
;
159 (void) mutex_lock(&ndmp_lock
);
160 if (ndmp_door_setup(opcode
))
163 if (ndmp_door_call())
166 /* number of sessions */
167 *size
= ndmp_door_get_int32(dec_ctx
);
169 *sinfo
= malloc((sizeof (ndmp_session_info_t
)) * *size
);
172 ndmp_errno
= ENDMP_MEM_ALLOC
;
176 for (i
= 0; i
< *size
; i
++, sp
++) {
177 status
= ndmp_door_get_int32(dec_ctx
);
178 if (status
== NDMP_SESSION_NODATA
)
181 /* connection common info */
182 sp
->nsi_sid
= ndmp_door_get_int32(dec_ctx
);
183 sp
->nsi_pver
= ndmp_door_get_int32(dec_ctx
);
184 sp
->nsi_auth
= ndmp_door_get_int32(dec_ctx
);
185 sp
->nsi_eof
= ndmp_door_get_int32(dec_ctx
);
186 sp
->nsi_cl_addr
= ndmp_door_get_string(dec_ctx
);
188 * scsi and tape data are same for all version,
191 /* connection common scsi info. */
192 sp
->nsi_scsi
.ns_scsi_open
= ndmp_door_get_int32(dec_ctx
);
193 sp
->nsi_scsi
.ns_adapter_name
= ndmp_door_get_string(dec_ctx
);
194 sp
->nsi_scsi
.ns_valid_target_set
= ndmp_door_get_int32(dec_ctx
);
195 if (sp
->nsi_scsi
.ns_valid_target_set
) {
196 sp
->nsi_scsi
.ns_scsi_id
= ndmp_door_get_int32(dec_ctx
);
197 sp
->nsi_scsi
.ns_lun
= ndmp_door_get_int32(dec_ctx
);
200 /* connection common tape info. */
201 sp
->nsi_tape
.nt_fd
= ndmp_door_get_int32(dec_ctx
);
202 if (sp
->nsi_tape
.nt_fd
!= -1) {
203 sp
->nsi_tape
.nt_rec_count
=
204 ndmp_door_get_uint64(dec_ctx
);
205 sp
->nsi_tape
.nt_mode
= ndmp_door_get_int32(dec_ctx
);
206 sp
->nsi_tape
.nt_dev_name
=
207 ndmp_door_get_string(dec_ctx
);
208 sp
->nsi_tape
.nt_adapter_name
=
209 ndmp_door_get_string(dec_ctx
);
210 sp
->nsi_tape
.nt_sid
= ndmp_door_get_int32(dec_ctx
);
211 sp
->nsi_tape
.nt_lun
= ndmp_door_get_int32(dec_ctx
);
213 /* all the V2 mover data are same as V3/V4 */
214 sp
->nsi_mover
.nm_state
= ndmp_door_get_int32(dec_ctx
);
215 sp
->nsi_mover
.nm_mode
= ndmp_door_get_int32(dec_ctx
);
216 sp
->nsi_mover
.nm_pause_reason
= ndmp_door_get_int32(dec_ctx
);
217 sp
->nsi_mover
.nm_halt_reason
= ndmp_door_get_int32(dec_ctx
);
218 sp
->nsi_mover
.nm_rec_size
= ndmp_door_get_uint64(dec_ctx
);
219 sp
->nsi_mover
.nm_rec_num
= ndmp_door_get_uint64(dec_ctx
);
220 sp
->nsi_mover
.nm_mov_pos
= ndmp_door_get_uint64(dec_ctx
);
221 sp
->nsi_mover
.nm_window_offset
= ndmp_door_get_uint64(dec_ctx
);
222 sp
->nsi_mover
.nm_window_length
= ndmp_door_get_uint64(dec_ctx
);
223 sp
->nsi_mover
.nm_sock
= ndmp_door_get_int32(dec_ctx
);
225 /* Read V3/V4 mover info */
226 if ((sp
->nsi_pver
== NDMP_V3
) || (sp
->nsi_pver
== NDMP_V4
)) {
227 sp
->nsi_mover
.nm_listen_sock
=
228 ndmp_door_get_int32(dec_ctx
);
229 sp
->nsi_mover
.nm_addr_type
=
230 ndmp_door_get_int32(dec_ctx
);
231 sp
->nsi_mover
.nm_tcp_addr
=
232 ndmp_door_get_string(dec_ctx
);
235 /* connection common data info */
236 sp
->nsi_data
.nd_oper
= ndmp_door_get_int32(dec_ctx
);
237 sp
->nsi_data
.nd_state
= ndmp_door_get_int32(dec_ctx
);
238 sp
->nsi_data
.nd_halt_reason
= ndmp_door_get_int32(dec_ctx
);
239 sp
->nsi_data
.nd_sock
= ndmp_door_get_int32(dec_ctx
);
240 sp
->nsi_data
.nd_addr_type
= ndmp_door_get_int32(dec_ctx
);
241 sp
->nsi_data
.nd_abort
= ndmp_door_get_int32(dec_ctx
);
242 sp
->nsi_data
.nd_read_offset
= ndmp_door_get_uint64(dec_ctx
);
243 sp
->nsi_data
.nd_read_length
= ndmp_door_get_uint64(dec_ctx
);
244 sp
->nsi_data
.nd_total_size
= ndmp_door_get_uint64(dec_ctx
);
245 sp
->nsi_data
.nd_env_len
= ndmp_door_get_uint64(dec_ctx
);
246 sp
->nsi_data
.nd_env
=
247 malloc(sizeof (ndmp_dt_pval_t
) * sp
->nsi_data
.nd_env_len
);
248 if (!sp
->nsi_data
.nd_env
) {
250 ndmp_errno
= ENDMP_MEM_ALLOC
;
253 ep
= sp
->nsi_data
.nd_env
;
254 for (j
= 0; j
< sp
->nsi_data
.nd_env_len
; j
++, ep
++) {
255 ep
->np_name
= ndmp_door_get_string(dec_ctx
);
256 ep
->np_value
= ndmp_door_get_string(dec_ctx
);
258 sp
->nsi_data
.nd_tcp_addr
= ndmp_door_get_string(dec_ctx
);
260 /* Read V2 data info */
261 if (sp
->nsi_pver
== NDMP_V2
) {
262 sp
->nsi_data
.nld_nlist_len
=
263 ndmp_door_get_int64(dec_ctx
);
264 sp
->nsi_data
.nd_nlist
.nld_nlist
=
265 malloc(sizeof (ndmp_dt_name_t
) *
266 sp
->nsi_data
.nld_nlist_len
);
267 if (!sp
->nsi_data
.nd_nlist
.nld_nlist
) {
269 ndmp_errno
= ENDMP_MEM_ALLOC
;
272 np
= sp
->nsi_data
.nd_nlist
.nld_nlist
;
274 for (j
= 0; j
< sp
->nsi_data
.nld_nlist_len
; j
++, np
++) {
275 np
->nn_name
= ndmp_door_get_string(dec_ctx
);
276 np
->nn_dest
= ndmp_door_get_string(dec_ctx
);
278 } else if ((sp
->nsi_pver
== NDMP_V3
) ||
279 (sp
->nsi_pver
== NDMP_V4
)) {
280 /* Read V3/V4 data info */
281 sp
->nsi_data
.nd_nlist
.nld_dt_v3
.dv3_listen_sock
=
282 ndmp_door_get_int32(dec_ctx
);
283 sp
->nsi_data
.nd_nlist
.nld_dt_v3
.dv3_bytes_processed
=
284 ndmp_door_get_uint64(dec_ctx
);
285 sp
->nsi_data
.nld_nlist_len
=
286 ndmp_door_get_uint64(dec_ctx
);
287 sp
->nsi_data
.nd_nlist
.nld_dt_v3
.dv3_nlist
=
288 malloc(sizeof (ndmp_dt_name_v3_t
) *
289 sp
->nsi_data
.nld_nlist_len
);
290 if (!sp
->nsi_data
.nd_nlist
.nld_dt_v3
.dv3_nlist
) {
292 ndmp_errno
= ENDMP_MEM_ALLOC
;
295 npv3
= sp
->nsi_data
.nd_nlist
.nld_dt_v3
.dv3_nlist
;
296 for (j
= 0; j
< sp
->nsi_data
.nld_nlist_len
;
298 npv3
->nn3_opath
= ndmp_door_get_string(dec_ctx
);
299 npv3
->nn3_dpath
= ndmp_door_get_string(dec_ctx
);
300 npv3
->nn3_node
= ndmp_door_get_uint64(dec_ctx
);
302 ndmp_door_get_uint64(dec_ctx
);
307 if (ndmp_door_fini())
310 (void) mutex_unlock(&ndmp_lock
);
313 (void) mutex_unlock(&ndmp_lock
);
318 ndmp_get_session_info_free(ndmp_session_info_t
*sinfo
, size_t size
)
320 ndmp_session_info_t
*sp
;
323 ndmp_dt_name_v3_t
*npv3
;
327 for (i
= 0; i
< size
; i
++, sp
++) {
328 free(sp
->nsi_cl_addr
);
329 free(sp
->nsi_scsi
.ns_adapter_name
);
330 if (sp
->nsi_tape
.nt_fd
!= -1) {
331 free(sp
->nsi_tape
.nt_dev_name
);
332 free(sp
->nsi_tape
.nt_adapter_name
);
334 if ((sp
->nsi_pver
== NDMP_V3
) || (sp
->nsi_pver
== NDMP_V4
))
335 free(sp
->nsi_mover
.nm_tcp_addr
);
337 ep
= sp
->nsi_data
.nd_env
;
338 for (j
= 0; j
< sp
->nsi_data
.nd_env_len
; j
++, ep
++) {
342 free(sp
->nsi_data
.nd_env
);
343 free(sp
->nsi_data
.nd_tcp_addr
);
345 if (sp
->nsi_pver
== NDMP_V2
) {
346 np
= sp
->nsi_data
.nd_nlist
.nld_nlist
;
347 for (j
= 0; j
< sp
->nsi_data
.nld_nlist_len
; j
++, np
++) {
351 free(sp
->nsi_data
.nd_nlist
.nld_nlist
);
352 } else if ((sp
->nsi_pver
== NDMP_V3
) ||
353 (sp
->nsi_pver
== NDMP_V4
)) {
354 npv3
= sp
->nsi_data
.nd_nlist
.nld_dt_v3
.dv3_nlist
;
355 for (j
= 0; j
< sp
->nsi_data
.nld_nlist_len
;
357 free(npv3
->nn3_opath
);
358 free(npv3
->nn3_dpath
);
360 free(sp
->nsi_data
.nd_nlist
.nld_dt_v3
.dv3_nlist
);
368 ndmp_get_stats(ndmp_stat_t
*statp
)
370 int opcode
= NDMP_GET_STAT
;
372 (void) mutex_lock(&ndmp_lock
);
374 ndmp_errno
= ENDMP_INVALID_ARG
;
378 if (ndmp_door_setup(opcode
))
381 if (ndmp_door_call())
384 statp
->ns_trun
= ndmp_door_get_uint32(dec_ctx
);
385 statp
->ns_twait
= ndmp_door_get_uint32(dec_ctx
);
386 statp
->ns_nbk
= ndmp_door_get_uint32(dec_ctx
);
387 statp
->ns_nrs
= ndmp_door_get_uint32(dec_ctx
);
388 statp
->ns_rfile
= ndmp_door_get_uint32(dec_ctx
);
389 statp
->ns_wfile
= ndmp_door_get_uint32(dec_ctx
);
390 statp
->ns_rdisk
= ndmp_door_get_uint64(dec_ctx
);
391 statp
->ns_wdisk
= ndmp_door_get_uint64(dec_ctx
);
392 statp
->ns_rtape
= ndmp_door_get_uint64(dec_ctx
);
393 statp
->ns_wtape
= ndmp_door_get_uint64(dec_ctx
);
395 if (ndmp_door_fini())
398 (void) mutex_unlock(&ndmp_lock
);
401 (void) mutex_unlock(&ndmp_lock
);
406 ndmp_door_status(void)
408 int opcode
= NDMP_GET_DOOR_STATUS
;
410 (void) mutex_lock(&ndmp_lock
);
411 if (ndmp_door_setup(opcode
))
414 if (ndmp_door_call())
417 if (ndmp_door_fini())
420 (void) mutex_unlock(&ndmp_lock
);
423 (void) mutex_unlock(&ndmp_lock
);
428 ndmp_door_setup(int opcode
)
430 /* Open channel to NDMP service */
431 if ((ndmp_door_fildes
== -1) &&
432 (ndmp_door_fildes
= open(NDMP_DOOR_SVC
, O_RDONLY
)) < 0) {
433 ndmp_errno
= ENDMP_DOOR_OPEN
;
437 buf
= malloc(NDMP_DOOR_SIZE
);
439 ndmp_errno
= ENDMP_MEM_ALLOC
;
443 enc_ctx
= ndmp_door_encode_start(buf
, NDMP_DOOR_SIZE
);
446 ndmp_errno
= ENDMP_DOOR_ENCODE_START
;
449 ndmp_door_put_uint32(enc_ctx
, opcode
);
459 if ((ndmp_door_encode_finish(enc_ctx
, &used
)) != 0) {
461 ndmp_errno
= ENDMP_DOOR_ENCODE_FINISH
;
466 arg
.data_size
= used
;
470 arg
.rsize
= NDMP_DOOR_SIZE
;
472 if (door_call(ndmp_door_fildes
, &arg
) < 0) {
474 ndmp_errno
= ENDMP_DOOR_SRV_TIMEOUT
;
475 (void) close(ndmp_door_fildes
);
476 ndmp_door_fildes
= -1;
480 dec_ctx
= ndmp_door_decode_start(arg
.data_ptr
, arg
.data_size
);
481 rc
= ndmp_door_get_uint32(dec_ctx
);
482 if (rc
!= NDMP_DOOR_SRV_SUCCESS
) {
484 ndmp_errno
= ENDMP_DOOR_SRV_OPERATION
;
493 if ((ndmp_door_decode_finish(dec_ctx
)) != 0) {
495 ndmp_errno
= ENDMP_DOOR_DECODE_FINISH
;