2 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
3 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
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.
66 typedef struct ndmp_command
{
68 int (*func
)(int argc
, char **argv
,
69 struct ndmp_command
*cur_cmd
);
73 static int ndmp_get_config(int, char **, ndmp_command_t
*);
74 static int ndmp_set_config(int, char **, ndmp_command_t
*);
75 static int ndmp_show_devices(int, char **, ndmp_command_t
*);
76 static int ndmp_show_sessions(int, char **, ndmp_command_t
*);
77 static int ndmp_kill_sessions(int, char **, ndmp_command_t
*);
78 static int ndmp_enable_auth(int, char **, ndmp_command_t
*);
79 static int ndmp_disable_auth(int, char **, ndmp_command_t
*);
80 static void ndmp_get_config_process(char *);
81 static void ndmp_set_config_process(char *arg
);
82 static int ndmp_get_password(char **);
84 static ndmp_command_t command_table
[] = {
85 { "get", ndmp_get_config
, HELP_GET_CONFIG
},
86 { "set", ndmp_set_config
, HELP_SET_CONFIG
},
87 { "show-devices", ndmp_show_devices
, HELP_SHOW_DEVICES
},
88 { "show-sessions", ndmp_show_sessions
, HELP_SHOW_SESSIONS
},
89 { "kill-sessions", ndmp_kill_sessions
, HELP_KILL_SESSIONS
},
90 { "enable", ndmp_enable_auth
, HELP_ENABLE_AUTH
},
91 { "disable", ndmp_disable_auth
, HELP_DISABLE_AUTH
}
94 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
96 static char *prop_table
[] = {
106 "restore-quarantine",
107 "overwrite-quarantine",
108 "zfs-force-override",
113 #define NDMPADM_NPROP (sizeof (prop_table) / sizeof (prop_table[0]))
115 typedef struct ndmp_auth
{
116 const char *auth_type
;
117 const char *username
;
118 const char *password
;
121 static ndmp_auth_t ndmp_auth_table
[] = {
122 { "cram-md5", "cram-md5-username", "cram-md5-password" },
123 { "cleartext", "cleartext-username", "cleartext-password" }
125 #define NAUTH (sizeof (ndmp_auth_table) / sizeof (ndmp_auth_table[0]))
126 #define NDMP_PASSWORD_RETRIES 3
128 #if !defined(TEXT_DOMAIN)
129 #define TEXT_DOMAIN "SYS_TEST"
133 get_usage(ndmp_help_t idx
)
136 case HELP_SET_CONFIG
:
137 return ("\tset [-p] <property=value> [[-p] property=value] "
139 case HELP_GET_CONFIG
:
140 return ("\tget [-p] [property] [[-p] property] ...\n");
141 case HELP_SHOW_DEVICES
:
142 return ("\tshow-devices\n");
143 case HELP_SHOW_SESSIONS
:
144 return ("\tshow-sessions [-i tape,scsi,data,mover] [id] ...\n");
145 case HELP_KILL_SESSIONS
:
146 return ("\tkill-sessions <id ...>\n");
147 case HELP_ENABLE_AUTH
:
148 return ("\tenable <-a auth-type> <-u username>\n");
149 case HELP_DISABLE_AUTH
:
150 return ("\tdisable <-a auth-type>\n");
157 * Display usage message. If we're inside a command, display only the usage for
158 * that command. Otherwise, iterate over the entire command table and display
159 * a complete usage message.
162 usage(boolean_t requested
, ndmp_command_t
*current_command
)
165 boolean_t show_properties
= B_FALSE
;
166 FILE *fp
= requested
? stdout
: stderr
;
168 if (current_command
== NULL
) {
170 gettext("Usage: ndmpadm subcommand args ...\n"));
172 gettext("where 'command' is one of the following:\n\n"));
174 for (i
= 0; i
< NCOMMAND
; i
++) {
175 (void) fprintf(fp
, "%s",
176 get_usage(command_table
[i
].nc_usage
));
178 (void) fprintf(fp
, gettext("\t\twhere %s can be either "
179 "%s or %s\n"), "'auth-type'", "'cram-md5'", "'cleartext'");
181 (void) fprintf(fp
, gettext("Usage:\n"));
182 (void) fprintf(fp
, "%s", get_usage(current_command
->nc_usage
));
183 if ((current_command
->nc_usage
== HELP_ENABLE_AUTH
) ||
184 (current_command
->nc_usage
== HELP_DISABLE_AUTH
))
185 (void) fprintf(fp
, gettext("\t\twhere %s can be either "
187 "'auth-type'", "'cram-md5'", "'cleartext'");
190 if (current_command
!= NULL
&&
191 (strcmp(current_command
->nc_name
, "set") == 0))
192 show_properties
= B_TRUE
;
194 if (show_properties
) {
196 gettext("\nThe following properties are supported:\n"));
198 (void) fprintf(fp
, gettext("\n\tPROPERTY"));
199 (void) fprintf(fp
, "\n\t%s", "-------------");
200 for (i
= 0; i
< NDMPADM_NPROP
; i
++)
201 (void) fprintf(fp
, "\n\t%s", prop_table
[i
]);
202 (void) fprintf(fp
, "\n");
205 exit(requested
? 0 : 2);
210 ndmp_get_config(int argc
, char **argv
, ndmp_command_t
*cur_cmd
)
217 * Get all the properties and variables ndmpadm is allowed
220 for (i
= 0; i
< NDMPADM_NPROP
; i
++) {
221 if (ndmp_get_prop(prop_table
[i
], &propval
)) {
222 (void) fprintf(stdout
, "\t%s=\n",
225 (void) fprintf(stdout
, "\t%s=%s\n",
226 prop_table
[i
], propval
);
230 } else if (argc
> 1) {
231 while ((c
= getopt(argc
, argv
, ":p:")) != -1) {
234 ndmp_get_config_process(optarg
);
237 (void) fprintf(stderr
, gettext("Option -%c "
238 "requires an operand\n"), optopt
);
241 (void) fprintf(stderr
, gettext("Unrecognized "
242 "option: -%c\n"), optopt
);
246 * optind is initialized to 1 if the -p option is not used,
247 * otherwise index to argv.
252 for (i
= 0; i
< argc
; i
++) {
253 if (strncmp(argv
[i
], "-p", 2) == 0)
256 ndmp_get_config_process(argv
[i
]);
263 ndmp_get_config_process(char *arg
)
268 for (j
= 0; j
< NDMPADM_NPROP
; j
++) {
269 if (strcmp(arg
, prop_table
[j
]) == 0) {
270 if (ndmp_get_prop(arg
, &propval
)) {
271 (void) fprintf(stdout
, "\t%s=\n", arg
);
273 (void) fprintf(stdout
, "\t%s=%s\n",
280 if (j
== NDMPADM_NPROP
) {
281 (void) fprintf(stdout
, gettext("\t%s is invalid property "
282 "or variable\n"), arg
);
288 ndmp_set_config(int argc
, char **argv
, ndmp_command_t
*cur_cmd
)
293 (void) fprintf(stderr
, gettext("Missing property=value "
295 usage(B_FALSE
, cur_cmd
);
297 while ((c
= getopt(argc
, argv
, ":p:")) != -1) {
300 ndmp_set_config_process(optarg
);
303 (void) fprintf(stderr
, gettext("Option -%c "
304 "requires an operand\n"), optopt
);
307 (void) fprintf(stderr
, gettext("Unrecognized "
308 "option: -%c\n"), optopt
);
312 * optind is initialized to 1 if the -p option is not used,
313 * otherwise index to argv.
318 for (i
= 0; i
< argc
; i
++) {
319 if (strncmp(argv
[i
], "-p", 2) == 0)
322 ndmp_set_config_process(argv
[i
]);
328 ndmp_set_config_process(char *propname
)
333 if ((propvalue
= strchr(propname
, '=')) == NULL
) {
334 (void) fprintf(stderr
, gettext("Missing value in "
335 "property=value argument for %s\n"), propname
);
341 if (*propname
== '\0') {
342 (void) fprintf(stderr
, gettext("Missing property in "
343 "property=value argument for %s\n"), propname
);
346 for (j
= 0; j
< NDMPADM_NPROP
; j
++) {
347 if (strcmp(propname
, prop_table
[j
]) == 0)
350 if (j
== NDMPADM_NPROP
) {
351 (void) fprintf(stdout
, gettext("%s is invalid property or "
352 "variable\n"), propname
);
355 ret
= ndmp_set_prop(propname
, propvalue
);
357 if (!ndmp_door_status()) {
358 if (ndmp_service_refresh() != 0)
359 (void) fprintf(stdout
, gettext("Could not "
360 "refesh property of service ndmpd\n"));
363 (void) fprintf(stdout
, gettext("Could not set property for "
364 "%s - %s\n"), propname
, ndmp_strerror(ndmp_errno
));
370 ndmp_show_devices(int argc
, char **argv
, ndmp_command_t
*cur_cmd
)
373 ndmp_devinfo_t
*dip
= NULL
;
376 if (ndmp_door_status()) {
377 (void) fprintf(stdout
,
378 gettext("Service ndmpd not running\n"));
382 ret
= ndmp_get_devinfo(&dip
, &size
);
385 (void) fprintf(stdout
,
386 gettext("Could not get device information\n"));
388 ndmp_devinfo_print(dip
, size
);
390 ndmp_get_devinfo_free(dip
, size
);
395 ndmp_show_sessions(int argc
, char **argv
, ndmp_command_t
*cur_cmd
)
397 ndmp_session_info_t
*sinfo
= NULL
;
398 ndmp_session_info_t
*sp
= NULL
;
403 char *type_subopts
[] = { "tape", "scsi", "data", "mover", NULL
};
405 if (ndmp_door_status()) {
406 (void) fprintf(stdout
,
407 gettext("Service ndmpd not running\n"));
411 /* Detail output if no option is specified */
413 statarg
= NDMP_CAT_ALL
;
416 while ((c
= getopt(argc
, argv
, ":i:")) != -1) {
419 while (*optarg
!= '\0') {
420 switch (getsubopt(&optarg
, type_subopts
,
423 statarg
|= NDMP_CAT_TAPE
;
426 statarg
|= NDMP_CAT_SCSI
;
429 statarg
|= NDMP_CAT_DATA
;
432 statarg
|= NDMP_CAT_MOVER
;
435 (void) fprintf(stderr
,
436 gettext("Invalid object "
437 "type '%s'\n"), value
);
438 usage(B_FALSE
, cur_cmd
);
443 (void) fprintf(stderr
,
444 gettext("Missing argument for "
445 "'%c' option\n"), optopt
);
446 usage(B_FALSE
, cur_cmd
);
449 (void) fprintf(stderr
,
450 gettext("Invalid option '%c'\n"), optopt
);
451 usage(B_FALSE
, cur_cmd
);
454 /* if -i and its argument are not specified, display all */
456 statarg
= NDMP_CAT_ALL
;
459 * optind is initialized to 1 if the -i option is not used, otherwise
465 ret
= ndmp_get_session_info(&sinfo
, &num
);
467 (void) fprintf(stdout
,
468 gettext("Could not get session information\n"));
471 ndmp_session_all_print(statarg
, sinfo
, num
);
473 for (i
= 0; i
< argc
; i
++) {
475 for (j
= 0; j
< num
; j
++, sp
++) {
476 if (sp
->nsi_sid
== atoi(argv
[i
])) {
477 ndmp_session_print(statarg
, sp
);
478 (void) fprintf(stdout
, "\n");
483 (void) fprintf(stdout
,
484 gettext("Session %d not "
485 "found\n"), atoi(argv
[i
]));
489 ndmp_get_session_info_free(sinfo
, num
);
496 ndmp_kill_sessions(int argc
, char **argv
, ndmp_command_t
*cur_cmd
)
500 if (ndmp_door_status()) {
501 (void) fprintf(stdout
,
502 gettext("Service ndmpd not running.\n"));
506 /* If no arg is specified, print the usage and exit */
508 usage(B_FALSE
, cur_cmd
);
510 for (i
= 1; i
< argc
; i
++) {
511 if (atoi(argv
[i
]) > 0) {
512 ret
= ndmp_terminate_session(atoi(argv
[i
]));
514 (void) fprintf(stderr
,
515 gettext("Invalid argument %s\n"), argv
[i
]);
519 (void) fprintf(stdout
,
520 gettext("Session id %d not found.\n"),
527 ndmp_get_password(char **password
)
532 for (i
= 0; i
< NDMP_PASSWORD_RETRIES
; i
++) {
534 * getpassphrase use the same buffer to return password, so
535 * copy the result in different buffer, before calling the
536 * getpassphrase again.
539 getpassphrase(gettext("Enter new password: "))) != NULL
) {
540 (void) strlcpy(pw2
, pw1
, sizeof (pw2
));
542 getpassphrase(gettext("Re-enter password: ")))
544 if (strncmp(pw1
, pw2
, strlen(pw1
)) == 0) {
548 (void) fprintf(stderr
,
549 gettext("Both password did not "
559 ndmp_enable_auth(int argc
, char **argv
, ndmp_command_t
*cur_cmd
)
561 char *auth_type
, *username
, *password
;
562 int c
, i
, auth_type_flag
= 0;
565 /* enable <-a auth-type> <-u username> */
567 usage(B_FALSE
, cur_cmd
);
570 while ((c
= getopt(argc
, argv
, ":a:u:")) != -1) {
573 auth_type
= strdup(optarg
);
576 username
= strdup(optarg
);
579 (void) fprintf(stderr
, gettext("Option -%c "
580 "requires an operand\n"), optopt
);
581 usage(B_FALSE
, cur_cmd
);
584 (void) fprintf(stderr
, gettext("Unrecognized "
585 "option: -%c\n"), optopt
);
586 usage(B_FALSE
, cur_cmd
);
590 if ((auth_type
) && (username
)) {
591 if (ndmp_get_password(&password
)) {
592 (void) fprintf(stderr
, gettext("Could not get correct "
593 "password, exiting..."));
599 (void) fprintf(stderr
, gettext("%s or %s can not be blank"),
600 "'auth-type'", "'username'");
606 if ((enc_password
= ndmp_base64_encode(password
)) == NULL
) {
607 (void) fprintf(stdout
,
608 gettext("Could not encode password - %s\n"),
609 ndmp_strerror(ndmp_errno
));
615 for (i
= 0; i
< NAUTH
; i
++) {
616 if (strncmp(auth_type
, ndmp_auth_table
[i
].auth_type
,
617 strlen(ndmp_auth_table
[i
].auth_type
)) == 0) {
619 if ((ndmp_set_prop(ndmp_auth_table
[i
].username
,
621 (void) fprintf(stdout
,
622 gettext("Could not set username - %s\n"),
623 ndmp_strerror(ndmp_errno
));
626 if ((ndmp_set_prop(ndmp_auth_table
[i
].password
,
627 enc_password
)) == -1) {
628 (void) fprintf(stdout
,
629 gettext("Could not set password - %s\n"),
630 ndmp_strerror(ndmp_errno
));
633 if (!ndmp_door_status() &&
634 (ndmp_service_refresh()) != 0) {
635 (void) fprintf(stdout
,
636 gettext("Could not refesh ndmpd service "
646 usage(B_FALSE
, cur_cmd
);
652 ndmp_disable_auth(int argc
, char **argv
, ndmp_command_t
*cur_cmd
)
655 int c
, i
, auth_type_flag
= 0;
657 /* disable <-a auth-type> */
659 usage(B_FALSE
, cur_cmd
);
662 while ((c
= getopt(argc
, argv
, ":a:")) != -1) {
665 auth_type
= strdup(optarg
);
668 (void) fprintf(stderr
, gettext("Option -%c "
669 "requires an operand\n"), optopt
);
672 (void) fprintf(stderr
, gettext("Unrecognized "
673 "option: -%c\n"), optopt
);
676 for (i
= 0; i
< NAUTH
; i
++) {
677 if (strncmp(auth_type
, ndmp_auth_table
[i
].auth_type
,
678 strlen(ndmp_auth_table
[i
].auth_type
)) == 0) {
680 if ((ndmp_set_prop(ndmp_auth_table
[i
].username
,
682 (void) fprintf(stdout
,
683 gettext("Could not clear username - %s\n"),
684 ndmp_strerror(ndmp_errno
));
687 if ((ndmp_set_prop(ndmp_auth_table
[i
].password
,
689 (void) fprintf(stdout
,
690 gettext("Could not clear password - %s\n"),
691 ndmp_strerror(ndmp_errno
));
694 if (!ndmp_door_status() &&
695 (ndmp_service_refresh()) != 0) {
696 (void) fprintf(stdout
, gettext("Could not "
697 "refesh ndmpd service properties\n"));
704 usage(B_FALSE
, cur_cmd
);
710 main(int argc
, char **argv
)
715 ndmp_command_t
*current_command
= NULL
;
717 (void) setlocale(LC_ALL
, "");
718 (void) textdomain(TEXT_DOMAIN
);
722 /* Make sure the user has specified some command. */
724 (void) fprintf(stderr
, gettext("Missing command.\n"));
725 usage(B_FALSE
, current_command
);
733 if (strcmp(cmdname
, "-?") == 0)
734 usage(B_TRUE
, current_command
);
737 * Run the appropriate sub-command.
739 for (i
= 0; i
< NCOMMAND
; i
++) {
740 if (strcmp(cmdname
, command_table
[i
].nc_name
) == 0) {
741 current_command
= &command_table
[i
];
742 ret
= command_table
[i
].func(argc
- 1, argv
+ 1,
749 (void) fprintf(stderr
, gettext("Unrecognized "
750 "command '%s'\n"), cmdname
);
751 usage(B_FALSE
, current_command
);