1/*
2 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3 */
4
5/*
6 * BSD 3 Clause License
7 *
8 * Copyright (c) 2007, The Storage Networking Industry Association.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 	- Redistributions of source code must retain the above copyright
14 *	  notice, this list of conditions and the following disclaimer.
15 *
16 * 	- Redistributions in binary form must reproduce the above copyright
17 *	  notice, this list of conditions and the following disclaimer in
18 *	  the documentation and/or other materials provided with the
19 *	  distribution.
20 *
21 *	- Neither the name of The Storage Networking Industry Association (SNIA)
22 *	  nor the names of its contributors may be used to endorse or promote
23 *	  products derived from this software without specific prior written
24 *	  permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38#include <stdio.h>
39#include <unistd.h>
40#include <errno.h>
41#include <locale.h>
42#include <libndmp.h>
43#include "ndmpadm.h"
44
45/* static functions prototype */
46static void ndmp_tprint_addr(char *, ndmp_ad_type_t, char *);
47static void ndmp_print_env(ndmp_session_info_t *);
48static void ndmp_connect_print_conn(ndmp_session_info_t *);
49static void ndmp_connect_print_scsi_v2(ndmp_session_info_t *);
50static void ndmp_connect_print_tape_v2(ndmp_session_info_t *);
51static void ndmp_connect_print_mover_v2(ndmp_session_info_t *);
52static void ndmp_connect_print_data_v2(ndmp_session_info_t *);
53static void ndmp_connect_print_v2(int, ndmp_session_info_t *);
54static void ndmp_connect_print_mover_v3(ndmp_session_info_t *);
55static void ndmp_connect_print_data_v3(ndmp_session_info_t *);
56static void ndmp_connect_print_v3(int, ndmp_session_info_t *);
57static void ndmp_connection_print(int, ndmp_session_info_t *);
58
59/* Boolean to string.  */
60#define	B2S(b)	((b) ? "Yes" : "No")
61
62/*
63 * Print the address type and IP address if the address type is tcp
64 */
65static void
66ndmp_tprint_addr(char *label, ndmp_ad_type_t addr_type, char *tcp_addr)
67{
68	if ((label == NULL) || (tcp_addr == NULL))
69		return;
70
71	switch (addr_type) {
72	case NDMP_AD_LOCAL:
73		(void) fprintf(stdout, gettext("\t%s type:\tLocal\n"), label);
74		break;
75	case NDMP_AD_TCP:
76		(void) fprintf(stdout, gettext("\t%s type:\tTCP\n"), label);
77		(void) fprintf(stdout, gettext("\t%s address:\t%s\n"),
78		    label, tcp_addr);
79		break;
80	case NDMP_AD_FC:
81		(void) fprintf(stdout, gettext("\t%s type:\tFC\n"), label);
82		break;
83	case NDMP_AD_IPC:
84		(void) fprintf(stdout, gettext("\t%s type:\tIPC\n"), label);
85		break;
86	default:
87		(void) fprintf(stdout,
88		    gettext("\t%s addr type unknown (0x%x)\n"),
89		    label, addr_type);
90	}
91}
92
93/*
94 * Print all the data environment variables for the active session
95 */
96static void
97ndmp_print_env(ndmp_session_info_t *si)
98{
99	int i, n;
100	ndmp_dt_pval_t *ep;
101
102	n = si->nsi_data.nd_env_len;
103	ep = si->nsi_data.nd_env;
104	for (i = 0; ep && i < n; i++, ep++) {
105		(void) fprintf(stdout, gettext("\tdata.env[%d]:\t%s: "),
106		    i, ep->np_name);
107		if ((ep->np_value != NULL) && (*ep->np_value != NULL))
108			(void) fprintf(stdout, "\"%s\"\n", ep->np_value);
109	}
110}
111
112/*
113 * Print common fields of the active connection.
114 */
115static void
116ndmp_connect_print_conn(ndmp_session_info_t *si)
117{
118	(void) fprintf(stdout, gettext("\tSession Id:\t%d\n"), si->nsi_sid);
119	(void) fprintf(stdout, gettext("\tProtocol version:\t%d\n"),
120	    si->nsi_pver);
121	(void) fprintf(stdout, gettext("\tAuthenticated:\t\t%s\n"),
122	    B2S(si->nsi_auth));
123	(void) fprintf(stdout, gettext("\tEOF:\t\t\t%s\n"), B2S(si->nsi_eof));
124	if (si->nsi_cl_addr != NULL)
125		(void) fprintf(stdout,
126		    gettext("\tClient address:\t\t%s\n"), si->nsi_cl_addr);
127}
128
129/*
130 * Print the connection SCSI info.
131 */
132static void
133ndmp_connect_print_scsi_v2(ndmp_session_info_t *si)
134{
135	(void) fprintf(stdout, gettext("\tscsi.open:\t\t%s\n"),
136	    B2S(si->nsi_scsi.ns_scsi_open != -1));
137	if (si->nsi_scsi.ns_adapter_name)
138		(void) fprintf(stdout, gettext("\tscsi.adapter:\t\t\"%s\"\n"),
139		    si->nsi_scsi.ns_adapter_name);
140	(void) fprintf(stdout, gettext("\tscsi.valid target:\t%s\n"),
141	    B2S(si->nsi_scsi.ns_valid_target_set));
142	if (si->nsi_scsi.ns_valid_target_set) {
143		(void) fprintf(stdout,
144		    gettext("\tscsi.SID:\t\t%d\n"), si->nsi_scsi.ns_scsi_id);
145		(void) fprintf(stdout,
146		    gettext("\tscsi.LUN:\t\t%d\n"), si->nsi_scsi.ns_lun);
147	}
148}
149
150/*
151 * Print the connection tape info.
152 */
153static void
154ndmp_connect_print_tape_v2(ndmp_session_info_t *si)
155{
156	if (si->nsi_tape.nt_fd != -1) {
157		(void) fprintf(stdout, gettext("\ttape.fd:\t\t%d\n"),
158		    si->nsi_tape.nt_fd);
159		(void) fprintf(stdout, gettext("\ttape.record count:\t%d\n"),
160		    (int)si->nsi_tape.nt_rec_count);
161
162		switch (si->nsi_tape.nt_mode) {
163		case NDMP_TP_READ_MODE:
164			(void) fprintf(stdout,
165			    gettext("\ttape.mode:\t\tRead-only\n"));
166			break;
167		case NDMP_TP_WRITE_MODE:
168			(void) fprintf(stdout,
169			    gettext("\ttape.mode:\t\tRead/Write\n"));
170			break;
171		case NDMP_TP_RAW1_MODE:
172			(void) fprintf(stdout,
173			    gettext("\ttape.mode:\t\tRaw\n"));
174			break;
175		default:
176			(void) fprintf(stdout,
177			    gettext("\ttape.mode:\t\tUnknown (0x%x)\n"),
178			    si->nsi_tape.nt_mode);
179		}
180
181		if (si->nsi_tape.nt_dev_name)
182			(void) fprintf(stdout,
183			    gettext("\ttape.device name:\t%s\n"),
184			    si->nsi_tape.nt_dev_name);
185		if (si->nsi_tape.nt_adapter_name)
186			(void) fprintf(stdout,
187			    gettext("\ttape.adapter name:\t\"%s\"\n"),
188			    si->nsi_tape.nt_adapter_name);
189		(void) fprintf(stdout,
190		    gettext("\ttape.SID:\t\t%d\n"), si->nsi_tape.nt_sid);
191		(void) fprintf(stdout,
192		    gettext("\ttape.LUN:\t\t%d\n"), si->nsi_tape.nt_lun);
193	} else
194		(void) fprintf(stdout, gettext("\ttape.device:\t\tNot open\n"));
195}
196
197/*
198 * Print the connection mover info.
199 */
200static void
201ndmp_connect_print_mover_v2(ndmp_session_info_t *si)
202{
203	switch (si->nsi_mover.nm_state) {
204	case NDMP_MV_STATE_IDLE:
205		(void) fprintf(stdout, gettext("\tmover.state:\t\tIdle\n"));
206		break;
207	case NDMP_MV_STATE_LISTEN:
208		(void) fprintf(stdout, gettext("\tmover.state:\t\tListen\n"));
209		break;
210	case NDMP_MV_STATE_ACTIVE:
211		(void) fprintf(stdout, gettext("\tmover.state:\t\tActive\n"));
212		break;
213	case NDMP_MV_STATE_PAUSED:
214		(void) fprintf(stdout, gettext("\tmover.state:\t\tPaused\n"));
215		break;
216	case NDMP_MV_STATE_HALTED:
217		(void) fprintf(stdout, gettext("\tmover.state:\t\tHalted\n"));
218		break;
219	default:
220		(void) fprintf(stdout,
221		    gettext("\tmover.state:\t\tUnknown (0x%x)\n"),
222		    si->nsi_mover.nm_state);
223	}
224
225	switch (si->nsi_mover.nm_mode) {
226	case NDMP_MV_MODE_READ:
227		(void) fprintf(stdout, gettext("\tmover.mode:\t\tRead\n"));
228		break;
229	case NDMP_MV_MODE_WRITE:
230		(void) fprintf(stdout, gettext("\tmover.mode:\t\tWrite\n"));
231		break;
232	default:
233		(void) fprintf(stdout,
234		    gettext("\tmover.mode:\t\tUnknown (0x%x)\n"),
235		    si->nsi_mover.nm_mode);
236	}
237
238	switch (si->nsi_mover.nm_pause_reason) {
239	case NDMP_MV_PAUSE_NA:
240		(void) fprintf(stdout, gettext("\tmover.pause reason:\tN/A\n"));
241		break;
242	case NDMP_MV_PAUSE_EOM:
243		(void) fprintf(stdout, gettext("\tmover.pause reason:\tEOM\n"));
244		break;
245	case NDMP_MV_PAUSE_EOF:
246		(void) fprintf(stdout, gettext("\tmover.pause reason:\tEOF\n"));
247		break;
248	case NDMP_MV_PAUSE_SEEK:
249		(void) fprintf(stdout,
250		    gettext("\tmover.pause reason:\tSeek\n"));
251		break;
252	case NDMP_MV_PAUSE_MEDIA_ERROR:
253		(void) fprintf(stdout,
254		    gettext("\tmover.pause reason:\tMedia Error\n"));
255		break;
256	default:
257		(void) fprintf(stdout,
258		    gettext("\tmover.pause reason:\tUnknown (0x%x)\n"),
259		    si->nsi_mover.nm_pause_reason);
260	}
261
262	switch (si->nsi_mover.nm_halt_reason) {
263	case NDMP_MV_HALT_NA:
264		(void) fprintf(stdout, gettext("\tmover.halt reason:\tN/A\n"));
265		break;
266	case NDMP_MV_HALT_CONNECT_CLOSED:
267		(void) fprintf(stdout,
268		    gettext("\tmover.halt reason:\tConnection closed\n"));
269		break;
270	case NDMP_MV_HALT_ABORTED:
271		(void) fprintf(stdout,
272		    gettext("\tmover.halt reason:\tAborted\n"));
273		break;
274	case NDMP_MV_HALT_INTERNAL_ERROR:
275		(void) fprintf(stdout,
276		    gettext("\tmover.halt reason:\tInternal error\n"));
277		break;
278	case NDMP_MV_HALT_CONNECT_ERROR:
279		(void) fprintf(stdout,
280		    gettext("\tmover.halt reason:\tConnection error\n"));
281		break;
282	default:
283		(void) fprintf(stdout,
284		    gettext("\tmover.halt reason:\tUnknown (0x%x)\n"),
285		    si->nsi_mover.nm_halt_reason);
286	}
287
288	(void) fprintf(stdout, gettext("\tmover.record size:\t%d\n"),
289	    (int)si->nsi_mover.nm_rec_size);
290	(void) fprintf(stdout, gettext("\tmover.record number:\t%d\n"),
291	    (int)si->nsi_mover.nm_rec_num);
292	(void) fprintf(stdout, gettext("\tmover.pos:\t\t%lld\n"),
293	    si->nsi_mover.nm_mov_pos);
294	(void) fprintf(stdout, gettext("\tmover.win off:\t\t%lld\n"),
295	    si->nsi_mover.nm_window_offset);
296	(void) fprintf(stdout, gettext("\tmover.win len:\t\t%lld\n"),
297	    si->nsi_mover.nm_window_length);
298	(void) fprintf(stdout, gettext("\tmover.data socket:\t%d\n"),
299	    si->nsi_mover.nm_sock);
300}
301
302/*
303 * Print the connection data info.
304 */
305static void
306ndmp_connect_print_data_v2(ndmp_session_info_t *si)
307{
308	int i;
309	ndmp_dt_name_t *np;
310
311	switch (si->nsi_data.nd_oper) {
312	case NDMP_DT_OP_NOACTION:
313		(void) fprintf(stdout, gettext("\tdata.operation:\t\tNone\n"));
314		break;
315	case NDMP_DT_OP_BACKUP:
316		(void) fprintf(stdout,
317		    gettext("\tdata.operation:\t\tBackup\n"));
318		break;
319	case NDMP_DT_OP_RECOVER:
320		(void) fprintf(stdout,
321		    gettext("\tdata.operation:\t\tRestore\n"));
322		break;
323	default:
324		(void) fprintf(stdout,
325		    gettext("\tdata.operation:\t\tUnknown (0x%x)\n"),
326		    si->nsi_data.nd_oper);
327	}
328
329	switch (si->nsi_data.nd_state) {
330	case NDMP_DT_STATE_IDLE:
331		(void) fprintf(stdout, gettext("\tdata.state:\t\tIdle\n"));
332		break;
333	case NDMP_DT_STATE_ACTIVE:
334		(void) fprintf(stdout, gettext("\tdata.state:\t\tActive\n"));
335		break;
336	case NDMP_DT_STATE_HALTED:
337		(void) fprintf(stdout, gettext("\tdata.state:\t\tHalted\n"));
338		break;
339	default:
340		(void) fprintf(stdout,
341		    gettext("\tdata.state:\t\tUnknown (0x%x)\n"),
342		    si->nsi_data.nd_state);
343	}
344
345	switch (si->nsi_data.nd_halt_reason) {
346	case NDMP_DT_HALT_NA:
347		(void) fprintf(stdout, gettext("\tdata.halt reason:\tN/A\n"));
348		break;
349	case NDMP_DT_HALT_SUCCESSFUL:
350		(void) fprintf(stdout,
351		    gettext("\tdata.halt reason:\tSuccessful\n"));
352		break;
353	case NDMP_DT_HALT_ABORTED:
354		(void) fprintf(stdout,
355		    gettext("\tdata.halt reason:\tAborted\n"));
356		break;
357	case NDMP_DT_HALT_INTERNAL_ERROR:
358		(void) fprintf(stdout,
359		    gettext("\tdata.halt reason:\tInternal error\n"));
360		break;
361	case NDMP_DT_HALT_CONNECT_ERROR:
362		(void) fprintf(stdout,
363		    gettext("\tdata.halt reason:\tConnection error\n"));
364		break;
365	default:
366		(void) fprintf(stdout,
367		    gettext("\tdata.halt reason:\tUnknown (0x%x)\n"),
368		    si->nsi_data.nd_halt_reason);
369	}
370
371	switch (si->nsi_data.nd_addr_type) {
372	case NDMP_AD_LOCAL:
373		(void) fprintf(stdout, gettext("\tdata.mover type:\tLocal\n"));
374		break;
375	case NDMP_AD_TCP:
376		(void) fprintf(stdout, gettext("\tdata.mover type:\tTCP\n"));
377		if (si->nsi_data.nd_tcp_addr)
378			(void) fprintf(stdout,
379			    gettext("\tdata.mover address:\t%s\n"),
380			    si->nsi_data.nd_tcp_addr);
381		(void) fprintf(stdout, gettext("\tdata.sock:\t%d\n"),
382		    si->nsi_data.nd_sock);
383		break;
384	default:
385		(void) fprintf(stdout,
386		    gettext("\tdata.mover type:\tUnknown (0x%x)\n"),
387		    si->nsi_data.nd_addr_type);
388	}
389
390	(void) fprintf(stdout, gettext("\tdata.aborted:\t\t%s\n"),
391	    B2S(si->nsi_data.nd_abort));
392	(void) fprintf(stdout, gettext("\tdata.read offset:\t%llu\n"),
393	    si->nsi_data.nd_read_offset);
394	(void) fprintf(stdout, gettext("\tdata.read length:\t%llu\n"),
395	    si->nsi_data.nd_read_length);
396	(void) fprintf(stdout, gettext("\tdata.total size:\t%llu\n"),
397	    si->nsi_data.nd_total_size);
398
399	ndmp_print_env(si);
400
401	np = si->nsi_data.nd_nlist.nld_nlist;
402	for (i = 0; np && i < (int)si->nsi_data.nld_nlist_len; i++, np++) {
403		if ((np->nn_name) && (np->nn_dest)) {
404			(void) fprintf(stdout,
405			    gettext("\tdata.nlist[%d]:\tname: "
406			    "\"%s\"\n\t\tdest:\"%s\"\n"),
407			    i, np->nn_name, np->nn_dest);
408		}
409	}
410}
411
412/*
413 * Print V2 connection info for the given category.
414 */
415static void
416ndmp_connect_print_v2(int cat, ndmp_session_info_t *si)
417{
418		if (cat & NDMP_CAT_SCSI)
419			ndmp_connect_print_scsi_v2(si);
420		if (cat & NDMP_CAT_TAPE)
421			ndmp_connect_print_tape_v2(si);
422		if (cat & NDMP_CAT_MOVER)
423			ndmp_connect_print_mover_v2(si);
424		if (cat & NDMP_CAT_DATA)
425			ndmp_connect_print_data_v2(si);
426}
427
428/*
429 * Print the V3 connection mover info.
430 */
431static void
432ndmp_connect_print_mover_v3(ndmp_session_info_t *si)
433{
434	switch (si->nsi_mover.nm_state) {
435	case NDMP_MV_STATE_IDLE:
436		(void) fprintf(stdout, gettext("\tmover.state:\t\tIdle\n"));
437		break;
438	case NDMP_MV_STATE_LISTEN:
439		(void) fprintf(stdout, gettext("\tmover.state:\t\tListen\n"));
440		break;
441	case NDMP_MV_STATE_ACTIVE:
442		(void) fprintf(stdout, gettext("\tmover.state:\t\tActive\n"));
443		break;
444	case NDMP_MV_STATE_PAUSED:
445		(void) fprintf(stdout, gettext("\tmover.state:\t\tPaused\n"));
446		break;
447	case NDMP_MV_STATE_HALTED:
448		(void) fprintf(stdout, gettext("\tmover.state:\t\tHalted\n"));
449		break;
450	default:
451		(void) fprintf(stdout,
452		    gettext("\tmover.state:\t\tUnknown (0x%x)\n"),
453		    si->nsi_mover.nm_state);
454	}
455
456	switch (si->nsi_mover.nm_mode) {
457	case NDMP_MV_MODE_READ:
458		(void) fprintf(stdout, gettext("\tmover.mode:\t\tRead\n"));
459		break;
460	case NDMP_MV_MODE_WRITE:
461		(void) fprintf(stdout, gettext("\tmover.mode:\t\tWrite\n"));
462		break;
463	default:
464		(void) fprintf(stdout,
465		    gettext("\tmover.mode:\t\tUnknown (0x%x)\n"),
466		    si->nsi_mover.nm_mode);
467	}
468
469	switch (si->nsi_mover.nm_pause_reason) {
470	case NDMP_MV_PAUSE_NA:
471		(void) fprintf(stdout, gettext("\tmover.pause reason:\tN/A\n"));
472		break;
473	case NDMP_MV_PAUSE_EOM:
474		(void) fprintf(stdout, gettext("\tmover.pause reason:\tEOM\n"));
475		break;
476	case NDMP_MV_PAUSE_EOF:
477		(void) fprintf(stdout, gettext("\tmover.pause reason:\tEOF\n"));
478		break;
479	case NDMP_MV_PAUSE_SEEK:
480		(void) fprintf(stdout,
481		    gettext("\tmover.pause reason:\tSeek\n"));
482		break;
483	case NDMP_MV_PAUSE_MEDIA_ERROR:
484		(void) fprintf(stdout,
485		    gettext("\tmover.pause reason:\tMedia Error\n"));
486		break;
487	case NDMP_MV_PAUSE_EOW:
488		(void) fprintf(stdout, gettext("\tmover.pause reason:\tEOW\n"));
489		break;
490	default:
491		(void) fprintf(stdout,
492		    gettext("\tmover.pause reason:\tUnknown (0x%x)\n"),
493		    si->nsi_mover.nm_pause_reason);
494	}
495
496	switch (si->nsi_mover.nm_halt_reason) {
497	case NDMP_MV_HALT_NA:
498		(void) fprintf(stdout, gettext("\tmover.halt reason:\tN/A\n"));
499		break;
500	case NDMP_MV_HALT_CONNECT_CLOSED:
501		(void) fprintf(stdout,
502		    gettext("\tmover.halt reason:\tConnection closed\n"));
503		break;
504	case NDMP_MV_HALT_ABORTED:
505		(void) fprintf(stdout,
506		    gettext("\tmover.halt reason:\tAborted\n"));
507		break;
508	case NDMP_MV_HALT_INTERNAL_ERROR:
509		(void) fprintf(stdout,
510		    gettext("\tmover.halt reason:\tInternal error\n"));
511		break;
512	case NDMP_MV_HALT_CONNECT_ERROR:
513		(void) fprintf(stdout,
514		    gettext("\tmover.halt reason:\tConnection error\n"));
515		break;
516	default:
517		(void) fprintf(stdout,
518		    gettext("\tmover.halt reason:\tUnknown (0x%x)\n"),
519		    si->nsi_mover.nm_halt_reason);
520	}
521
522	(void) fprintf(stdout, gettext("\tmover.record size:\t%d\n"),
523	    (int)si->nsi_mover.nm_rec_size);
524	(void) fprintf(stdout, gettext("\tmover.record number:\t%d\n"),
525	    (int)si->nsi_mover.nm_rec_num);
526	(void) fprintf(stdout, gettext("\tmover.pos:\t\t%lld\n"),
527	    si->nsi_mover.nm_mov_pos, si->nsi_mover.nm_mov_pos);
528
529	(void) fprintf(stdout, gettext("\tmover.win len:\t\t%lld\n"),
530	    si->nsi_mover.nm_window_length, si->nsi_mover.nm_window_length);
531
532	(void) fprintf(stdout, gettext("\tmover.win off:\t\t%lld\n"),
533	    si->nsi_mover.nm_window_offset);
534	switch (si->nsi_mover.nm_state) {
535	case NDMP_MV_STATE_IDLE:
536		if (si->nsi_mover.nm_listen_sock != -1)
537			(void) fprintf(stdout,
538			    gettext("\tmover.listenSock:\t%d\n"),
539			    si->nsi_mover.nm_listen_sock);
540		if (si->nsi_mover.nm_sock != -1)
541			(void) fprintf(stdout, gettext("\tmover.sock:\t%d\n"),
542			    si->nsi_mover.nm_sock);
543		break;
544	case NDMP_MV_STATE_LISTEN:
545		(void) fprintf(stdout, gettext("\tmover.listen socket:\t%d\n"),
546		    si->nsi_mover.nm_listen_sock);
547		ndmp_tprint_addr(gettext("mover.listen"),
548		    si->nsi_mover.nm_addr_type, si->nsi_mover.nm_tcp_addr);
549		break;
550	case NDMP_MV_STATE_ACTIVE:
551	case NDMP_MV_STATE_PAUSED:
552	case NDMP_MV_STATE_HALTED:
553		(void) fprintf(stdout, gettext("\tmover.data socket:\t%d\n"),
554		    si->nsi_mover.nm_sock);
555		ndmp_tprint_addr(gettext("mover.data connection"),
556		    si->nsi_mover.nm_addr_type, si->nsi_mover.nm_tcp_addr);
557		break;
558	}
559}
560
561/*
562 * Print the connection data info.
563 */
564static void
565ndmp_connect_print_data_v3(ndmp_session_info_t *si)
566{
567	int i;
568	ndmp_dt_name_v3_t *np;
569
570	switch (si->nsi_data.nd_oper) {
571	case NDMP_DT_OP_NOACTION:
572		(void) fprintf(stdout, gettext("\tdata.operation:\t\tNone\n"));
573		break;
574	case NDMP_DT_OP_BACKUP:
575		(void) fprintf(stdout,
576		    gettext("\tdata.operation:\t\tBackup\n"));
577		break;
578	case NDMP_DT_OP_RECOVER:
579		(void) fprintf(stdout,
580		    gettext("\tdata.operation:\t\tRestore\n"));
581		break;
582	default:
583		(void) fprintf(stdout,
584		    gettext("\tdata.operation:\t\tUnknown (0x%x)\n"),
585		    si->nsi_data.nd_oper);
586	}
587
588	switch (si->nsi_data.nd_state) {
589	case NDMP_DT_STATE_IDLE:
590		(void) fprintf(stdout, gettext("\tdata.state:\t\tIdle\n"));
591		break;
592	case NDMP_DT_STATE_ACTIVE:
593		(void) fprintf(stdout, gettext("\tdata.state:\t\tActive\n"));
594		break;
595	case NDMP_DT_STATE_HALTED:
596		(void) fprintf(stdout, gettext("\tdata.state:\t\tHalted\n"));
597		break;
598	case NDMP_DT_STATE_LISTEN:
599		(void) fprintf(stdout, gettext("\tdata.state:\t\tListen\n"));
600		break;
601	case NDMP_DT_STATE_CONNECTED:
602		(void) fprintf(stdout, gettext("\tdata.state:\t\tConnected\n"));
603		break;
604	default:
605		(void) fprintf(stdout,
606		    gettext("\tdata.state:\t\tUnknown (0x%x)\n"),
607		    si->nsi_data.nd_state);
608	}
609
610	switch (si->nsi_data.nd_halt_reason) {
611	case NDMP_DT_HALT_NA:
612		(void) fprintf(stdout,
613		    gettext("\tdata.halt reason:\tN/A\n"));
614		break;
615	case NDMP_DT_HALT_SUCCESSFUL:
616		(void) fprintf(stdout,
617		    gettext("\tdata.halt reason:\tSuccessful\n"));
618		break;
619	case NDMP_DT_HALT_ABORTED:
620		(void) fprintf(stdout,
621		    gettext("\tdata.halt reason:\tAborted\n"));
622		break;
623	case NDMP_DT_HALT_INTERNAL_ERROR:
624		(void) fprintf(stdout,
625		    gettext("\tdata.halt reason:\tInternal error\n"));
626		break;
627	case NDMP_DT_HALT_CONNECT_ERROR:
628		(void) fprintf(stdout,
629		    gettext("\tdata.halt reason:\tConnection error\n"));
630		break;
631	default:
632		(void) fprintf(stdout,
633		    gettext("\tdata.halt reason:\tUnknown (0x%x)\n"),
634		    si->nsi_data.nd_halt_reason);
635	}
636
637	switch (si->nsi_data.nd_state) {
638	case NDMP_DT_STATE_IDLE:
639		if (si->nsi_data.nd_sock != -1)
640			(void) fprintf(stdout,
641			    gettext("\tdata.data socket:\t%d\n"),
642			    si->nsi_data.nd_sock);
643		if (si->nsi_data.nd_nlist.nld_dt_v3.dv3_listen_sock != -1)
644			(void) fprintf(stdout,
645			    gettext("\tdata.data socket:\t%d\n"),
646			    si->nsi_data.nd_nlist.nld_dt_v3.dv3_listen_sock);
647		break;
648	case NDMP_DT_STATE_LISTEN:
649		(void) fprintf(stdout, gettext("\tdata.listen socket:\t%d\n"),
650		    si->nsi_data.nd_nlist.nld_dt_v3.dv3_listen_sock);
651		ndmp_tprint_addr(gettext("data.listen"),
652		    si->nsi_data.nd_addr_type, si->nsi_data.nd_tcp_addr);
653		break;
654	case NDMP_DT_STATE_ACTIVE:
655	case NDMP_DT_STATE_HALTED:
656	case NDMP_DT_STATE_CONNECTED:
657		(void) fprintf(stdout, gettext("\tdata.data socket:\t%d\n"),
658		    si->nsi_data.nd_sock);
659		ndmp_tprint_addr(gettext("data.data"),
660		    si->nsi_data.nd_addr_type, si->nsi_data.nd_tcp_addr);
661		break;
662	}
663
664	(void) fprintf(stdout, gettext("\tdata.aborted:\t\t%s\n"),
665	    B2S(si->nsi_data.nd_abort));
666	(void) fprintf(stdout, gettext("\tdata.read offset:\t%llu\n"),
667	    si->nsi_data.nd_read_offset);
668	(void) fprintf(stdout, gettext("\tdata.read length:\t%llu\n"),
669	    si->nsi_data.nd_read_length);
670	(void) fprintf(stdout, gettext("\tdata.total size:\t%llu\n"),
671	    si->nsi_data.nd_total_size);
672	(void) fprintf(stdout,
673	    gettext("\tdata.bytes processed:\t%lld\n"),
674	    si->nsi_data.nd_nlist.nld_dt_v3.dv3_bytes_processed);
675
676	ndmp_print_env(si);
677
678	np = si->nsi_data.nd_nlist.nld_dt_v3.dv3_nlist;
679	for (i = 0; np && i < si->nsi_data.nld_nlist_len; i++, np++) {
680		(void) fprintf(stdout, gettext("\tdata.nlist[%d]:\tname:\n"),
681		    i);
682		if (np->nn3_opath)
683			(void) fprintf(stdout,
684			    gettext("\t\torig: \"%s\"\n"), np->nn3_opath);
685		if (np->nn3_dpath)
686			(void) fprintf(stdout,
687			    gettext("\t\tdest: \"%s\"\n"), np->nn3_dpath);
688		else
689			(void) fprintf(stdout, gettext("\t\tdest:\n"));
690		(void) fprintf(stdout,
691		    gettext("\t\tnode: %lld\n"), np->nn3_node);
692		(void) fprintf(stdout, gettext("\t\tfh_info: %lld\n"),
693		    np->nn3_fh_info);
694	}
695}
696
697/*
698 * Print V3 connection info for given category.
699 */
700static void
701ndmp_connect_print_v3(int cat, ndmp_session_info_t *si)
702{
703	if (cat & NDMP_CAT_SCSI)
704		ndmp_connect_print_scsi_v2(si);
705	if (cat & NDMP_CAT_TAPE)
706		ndmp_connect_print_tape_v2(si);
707	if (cat & NDMP_CAT_MOVER)
708		ndmp_connect_print_mover_v3(si);
709	if (cat & NDMP_CAT_DATA)
710		ndmp_connect_print_data_v3(si);
711}
712
713/*
714 * Print the list of all active sessions to the clients.  For each version,
715 * call the appropriate print function.
716 */
717static void
718ndmp_connection_print(int cat, ndmp_session_info_t *si)
719{
720	switch (si->nsi_pver) {
721	case NDMP_V2:
722		ndmp_connect_print_conn(si);
723		ndmp_connect_print_v2(cat, si);
724		break;
725	case NDMP_V3:
726	case NDMP_V4:
727		ndmp_connect_print_conn(si);
728		ndmp_connect_print_v3(cat, si);
729		break;
730	default:
731		(void) fprintf(stdout,
732		    gettext("Invalid version %d"), si->nsi_pver);
733	}
734}
735
736/*
737 * Print the list of all active sessions to the clients.
738 */
739void
740ndmp_session_all_print(int cat, ndmp_session_info_t *si, size_t num)
741{
742	int i;
743	ndmp_session_info_t *sp;
744
745	sp = si;
746	for (i = 0; i < num; i++, sp++) {
747		ndmp_connection_print(cat, sp);
748		(void) fprintf(stdout, "\n");
749	}
750
751	if (num == 0) {
752		(void) fprintf(stdout, gettext("No active session.\n"));
753	} else {
754		(void) fprintf(stdout, gettext("%d active sessions.\n"), num);
755	}
756}
757
758/*
759 * Print the connection information for the given category.
760 */
761void
762ndmp_session_print(int cat,  ndmp_session_info_t *si)
763{
764	ndmp_connection_print(cat, si);
765}
766
767void
768ndmp_devinfo_print(ndmp_devinfo_t *dip, size_t size)
769{
770	int i;
771
772	if (dip == NULL) {
773		(void) fprintf(stdout, gettext("No device attached.\n"));
774		return;
775	}
776
777	for (i = 0; i < size; i++, dip++) {
778		/*
779		 * Don't print dead links.
780		 */
781		if ((access(dip->nd_name, F_OK) == -1) && (errno == ENOENT))
782			continue;
783		switch (dip->nd_dev_type) {
784		case NDMP_SINQ_TAPE_ROBOT:
785			(void) fprintf(stdout, gettext("Robot (Changer):\n"));
786			break;
787		case NDMP_SINQ_SEQ_ACCESS_DEVICE:
788			(void) fprintf(stdout, gettext("Tape drive(s):\n"));
789			break;
790		}
791		if (dip->nd_name)
792			(void) fprintf(stdout,
793			    gettext("\tName      : %s\n"), dip->nd_name);
794		(void) fprintf(stdout,
795		    gettext("\tLUN #     : %d\n"), dip->nd_lun);
796		(void) fprintf(stdout,
797		    gettext("\tSCSI ID # : %d\n"), dip->nd_sid);
798		if (dip->nd_vendor)
799			(void) fprintf(stdout,
800			    gettext("\tVendor    : %s\n"), dip->nd_vendor);
801		if (dip->nd_product)
802			(void) fprintf(stdout,
803			    gettext("\tProduct   : %s\n"), dip->nd_product);
804		if (dip->nd_revision)
805			(void) fprintf(stdout,
806			    gettext("\tRevision  : %s\n"), dip->nd_revision);
807		if (dip->nd_serial)
808			(void) fprintf(stdout,
809			    gettext("\tSerial    : %s\n"), dip->nd_serial);
810		if (dip->nd_wwn)
811			(void) fprintf(stdout,
812			    gettext("\tWWN       : %s\n"), dip->nd_wwn);
813		(void) fprintf(stdout, "\n");
814	}
815}
816