xref: /titanic_44/usr/src/cmd/ndmpadm/ndmpadm_main.c (revision 45405cce0657d01714b3d014a0facf3bdce45736)
1 /*
2  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
3  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
4  */
5 
6 /*
7  * BSD 3 Clause License
8  *
9  * Copyright (c) 2007, The Storage Networking Industry Association.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 	- Redistributions of source code must retain the above copyright
15  *	  notice, this list of conditions and the following disclaimer.
16  *
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
20  *	  distribution.
21  *
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
25  *	  permission.
26  *
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.
38  */
39 #include <assert.h>
40 #include <ctype.h>
41 #include <libgen.h>
42 #include <libintl.h>
43 #include <locale.h>
44 #include <stddef.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <strings.h>
48 #include <unistd.h>
49 #include <fcntl.h>
50 #include <sys/stat.h>
51 #include <door.h>
52 #include <sys/mman.h>
53 #include <libndmp.h>
54 #include "ndmpadm.h"
55 
56 typedef enum {
57 	HELP_GET_CONFIG,
58 	HELP_SET_CONFIG,
59 	HELP_SHOW_DEVICES,
60 	HELP_SHOW_SESSIONS,
61 	HELP_KILL_SESSIONS,
62 	HELP_ENABLE_AUTH,
63 	HELP_DISABLE_AUTH
64 } ndmp_help_t;
65 
66 typedef struct ndmp_command {
67 	const char	*nc_name;
68 	int		(*func)(int argc, char **argv,
69 			    struct ndmp_command *cur_cmd);
70 	ndmp_help_t	nc_usage;
71 } ndmp_command_t;
72 
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 **);
83 
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 }
92 };
93 
94 #define	NCOMMAND	(sizeof (command_table) / sizeof (command_table[0]))
95 
96 static char *prop_table[] = {
97 	"debug-path",
98 	"dump-pathnode",
99 	"tar-pathnode",
100 	"ignore-ctime",
101 	"token-maxseq",
102 	"version",
103 	"dar-support",
104 	"tcp-port",
105 	"backup-quarantine",
106 	"restore-quarantine",
107 	"overwrite-quarantine",
108 	"zfs-force-override",
109 	"drive-type",
110 	"debug-mode"
111 };
112 
113 #define	NDMPADM_NPROP	(sizeof (prop_table) / sizeof (prop_table[0]))
114 
115 typedef struct ndmp_auth {
116 	const char *auth_type;
117 	const char *username;
118 	const char *password;
119 } ndmp_auth_t;
120 
121 static ndmp_auth_t ndmp_auth_table[] = {
122 	{ "cram-md5", "cram-md5-username", "cram-md5-password" },
123 	{ "cleartext", "cleartext-username", "cleartext-password" }
124 };
125 #define	NAUTH	(sizeof (ndmp_auth_table) / sizeof (ndmp_auth_table[0]))
126 #define	NDMP_PASSWORD_RETRIES	3
127 
128 #if !defined(TEXT_DOMAIN)
129 #define	TEXT_DOMAIN	"SYS_TEST"
130 #endif
131 
132 static const char *
133 get_usage(ndmp_help_t idx)
134 {
135 	switch (idx) {
136 	case HELP_SET_CONFIG:
137 		return ("\tset [-p] <property=value> [[-p] property=value] "
138 		    "...\n");
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");
151 	}
152 
153 	return (NULL);
154 }
155 
156 /*
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.
160  */
161 static void
162 usage(boolean_t requested, ndmp_command_t *current_command)
163 {
164 	int i;
165 	boolean_t show_properties = B_FALSE;
166 	FILE *fp = requested ? stdout : stderr;
167 
168 	if (current_command == NULL) {
169 		(void) fprintf(fp,
170 		    gettext("Usage: ndmpadm subcommand args ...\n"));
171 		(void) fprintf(fp,
172 		    gettext("where 'command' is one of the following:\n\n"));
173 
174 		for (i = 0; i < NCOMMAND; i++) {
175 			(void) fprintf(fp, "%s",
176 			    get_usage(command_table[i].nc_usage));
177 		}
178 		(void) fprintf(fp, gettext("\t\twhere %s can be either "
179 		    "%s or %s\n"), "'auth-type'", "'cram-md5'", "'cleartext'");
180 	} else {
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 "
186 			    "%s or %s\n"),
187 			    "'auth-type'", "'cram-md5'", "'cleartext'");
188 	}
189 
190 	if (current_command != NULL &&
191 	    (strcmp(current_command->nc_name, "set") == 0))
192 		show_properties = B_TRUE;
193 
194 	if (show_properties) {
195 		(void) fprintf(fp,
196 		    gettext("\nThe following properties are supported:\n"));
197 
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");
203 	}
204 
205 	exit(requested ? 0 : 2);
206 }
207 
208 /*ARGSUSED*/
209 static int
210 ndmp_get_config(int argc, char **argv, ndmp_command_t *cur_cmd)
211 {
212 	char *propval;
213 	int i, c;
214 
215 	if (argc == 1) {
216 		/*
217 		 * Get all the properties and variables ndmpadm is allowed
218 		 * to see.
219 		 */
220 		for (i = 0; i < NDMPADM_NPROP; i++) {
221 			if (ndmp_get_prop(prop_table[i], &propval)) {
222 				(void) fprintf(stdout, "\t%s=\n",
223 				    prop_table[i]);
224 			} else {
225 				(void) fprintf(stdout, "\t%s=%s\n",
226 				    prop_table[i], propval);
227 				free(propval);
228 			}
229 		}
230 	} else if (argc > 1) {
231 		while ((c = getopt(argc, argv, ":p:")) != -1) {
232 			switch (c) {
233 			case 'p':
234 				ndmp_get_config_process(optarg);
235 				break;
236 			case ':':
237 				(void) fprintf(stderr, gettext("Option -%c "
238 				    "requires an operand\n"), optopt);
239 				break;
240 			case '?':
241 				(void) fprintf(stderr, gettext("Unrecognized "
242 				    "option: -%c\n"), optopt);
243 			}
244 		}
245 		/*
246 		 * optind is initialized to 1 if the -p option is not used,
247 		 * otherwise index to argv.
248 		 */
249 		argc -= optind;
250 		argv += optind;
251 
252 		for (i = 0; i < argc; i++) {
253 			if (strncmp(argv[i], "-p", 2) == 0)
254 				continue;
255 
256 			ndmp_get_config_process(argv[i]);
257 		}
258 	}
259 	return (0);
260 }
261 
262 static void
263 ndmp_get_config_process(char *arg)
264 {
265 	int j;
266 	char *propval;
267 
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);
272 			} else {
273 				(void) fprintf(stdout, "\t%s=%s\n",
274 				    arg, propval);
275 				free(propval);
276 			}
277 			break;
278 		}
279 	}
280 	if (j == NDMPADM_NPROP) {
281 		(void) fprintf(stdout, gettext("\t%s is invalid property "
282 		    "or variable\n"), arg);
283 	}
284 }
285 
286 /*ARGSUSED*/
287 static int
288 ndmp_set_config(int argc, char **argv, ndmp_command_t *cur_cmd)
289 {
290 	int c, i;
291 
292 	if (argc < 2) {
293 		(void) fprintf(stderr, gettext("Missing property=value "
294 		    "argument\n"));
295 		usage(B_FALSE, cur_cmd);
296 	}
297 	while ((c = getopt(argc, argv, ":p:")) != -1) {
298 		switch (c) {
299 		case 'p':
300 			ndmp_set_config_process(optarg);
301 			break;
302 		case ':':
303 			(void) fprintf(stderr, gettext("Option -%c "
304 			    "requires an operand\n"), optopt);
305 			break;
306 		case '?':
307 			(void) fprintf(stderr, gettext("Unrecognized "
308 			    "option: -%c\n"), optopt);
309 		}
310 	}
311 	/*
312 	 * optind is initialized to 1 if the -p option is not used,
313 	 * otherwise index to argv.
314 	 */
315 	argc -= optind;
316 	argv += optind;
317 
318 	for (i = 0; i < argc; i++) {
319 		if (strncmp(argv[i], "-p", 2) == 0)
320 			continue;
321 
322 		ndmp_set_config_process(argv[i]);
323 	}
324 	return (0);
325 }
326 
327 static void
328 ndmp_set_config_process(char *propname)
329 {
330 	char *propvalue;
331 	int ret, j;
332 
333 	if ((propvalue = strchr(propname, '=')) == NULL) {
334 		(void) fprintf(stderr, gettext("Missing value in "
335 		    "property=value argument for %s\n"), propname);
336 			return;
337 	}
338 	*propvalue = '\0';
339 	propvalue++;
340 
341 	if (*propname == '\0') {
342 		(void) fprintf(stderr, gettext("Missing property in "
343 		    "property=value argument for %s\n"), propname);
344 			return;
345 	}
346 	for (j = 0; j < NDMPADM_NPROP; j++) {
347 		if (strcmp(propname, prop_table[j]) == 0)
348 			break;
349 	}
350 	if (j == NDMPADM_NPROP) {
351 		(void) fprintf(stdout, gettext("%s is invalid property or "
352 		    "variable\n"), propname);
353 		return;
354 	}
355 	ret = ndmp_set_prop(propname, propvalue);
356 	if (ret != -1) {
357 		if (!ndmp_door_status()) {
358 			if (ndmp_service_refresh() == -1)
359 				(void) fprintf(stdout, gettext("Could not "
360 				    "refesh property of service ndmpd\n"));
361 		}
362 	} else {
363 		(void) fprintf(stdout, gettext("Could not set property for "
364 		    "%s - %s\n"), propname, ndmp_strerror(ndmp_errno));
365 	}
366 }
367 
368 /*ARGSUSED*/
369 static int
370 ndmp_show_devices(int argc, char **argv, ndmp_command_t *cur_cmd)
371 {
372 	int ret;
373 	ndmp_devinfo_t *dip = NULL;
374 	size_t size;
375 
376 	if (ndmp_door_status()) {
377 		(void) fprintf(stdout,
378 		    gettext("Service ndmpd not running\n"));
379 		return (-1);
380 	}
381 
382 	ret = ndmp_get_devinfo(&dip, &size);
383 
384 	if (ret == -1)
385 		(void) fprintf(stdout,
386 		    gettext("Could not get device information\n"));
387 	else
388 		ndmp_devinfo_print(dip, size);
389 
390 	ndmp_get_devinfo_free(dip, size);
391 	return (0);
392 }
393 
394 static int
395 ndmp_show_sessions(int argc, char **argv, ndmp_command_t *cur_cmd)
396 {
397 	ndmp_session_info_t *sinfo = NULL;
398 	ndmp_session_info_t *sp = NULL;
399 	uint_t num;
400 	int c, ret, i, j;
401 	int statarg = 0;
402 	char *value;
403 	char *type_subopts[] = { "tape", "scsi", "data", "mover", NULL };
404 
405 	if (ndmp_door_status()) {
406 		(void) fprintf(stdout,
407 		    gettext("Service ndmpd not running\n"));
408 		return (-1);
409 	}
410 
411 	/* Detail output if no option is specified */
412 	if (argc == 1) {
413 		statarg = NDMP_CAT_ALL;
414 	} else {
415 		statarg = 0;
416 		while ((c = getopt(argc, argv, ":i:")) != -1) {
417 			switch (c) {
418 			case 'i':
419 				while (*optarg != '\0') {
420 					switch (getsubopt(&optarg, type_subopts,
421 					    &value)) {
422 					case 0:
423 						statarg |= NDMP_CAT_TAPE;
424 						break;
425 					case 1:
426 						statarg |= NDMP_CAT_SCSI;
427 						break;
428 					case 2:
429 						statarg |= NDMP_CAT_DATA;
430 						break;
431 					case 3:
432 						statarg |= NDMP_CAT_MOVER;
433 						break;
434 					default:
435 						(void) fprintf(stderr,
436 						    gettext("Invalid object "
437 						    "type '%s'\n"), value);
438 						usage(B_FALSE, cur_cmd);
439 					}
440 				}
441 				break;
442 			case ':':
443 				(void) fprintf(stderr,
444 				    gettext("Missing argument for "
445 				    "'%c' option\n"), optopt);
446 				usage(B_FALSE, cur_cmd);
447 				break;
448 			case '?':
449 				(void) fprintf(stderr,
450 				    gettext("Invalid option '%c'\n"), optopt);
451 				usage(B_FALSE, cur_cmd);
452 			}
453 		}
454 		/* if -i and its argument are not specified, display all */
455 		if (statarg == 0)
456 			statarg = NDMP_CAT_ALL;
457 	}
458 	/*
459 	 * optind is initialized to 1 if the -i option is not used, otherwise
460 	 * index to argv.
461 	 */
462 	argc -= optind;
463 	argv += optind;
464 
465 	ret = ndmp_get_session_info(&sinfo, &num);
466 	if (ret == -1) {
467 		(void) fprintf(stdout,
468 		    gettext("Could not get session information\n"));
469 	} else {
470 		if (argc == 0) {
471 			ndmp_session_all_print(statarg, sinfo, num);
472 		} else {
473 			for (i = 0; i < argc; i++) {
474 				sp = sinfo;
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");
479 						break;
480 					}
481 				}
482 				if (j == num) {
483 					(void) fprintf(stdout,
484 					    gettext("Session %d not "
485 					    "found\n"), atoi(argv[i]));
486 				}
487 			}
488 		}
489 		ndmp_get_session_info_free(sinfo, num);
490 	}
491 	return (0);
492 }
493 
494 /*ARGSUSED*/
495 static int
496 ndmp_kill_sessions(int argc, char **argv, ndmp_command_t *cur_cmd)
497 {
498 	int ret, i;
499 
500 	if (ndmp_door_status()) {
501 		(void) fprintf(stdout,
502 		    gettext("Service ndmpd not running.\n"));
503 		return (-1);
504 	}
505 
506 	/* If no arg is specified, print the usage and exit */
507 	if (argc == 1)
508 		usage(B_FALSE, cur_cmd);
509 
510 	for (i = 1; i < argc; i++) {
511 		if (atoi(argv[i]) > 0) {
512 			ret = ndmp_terminate_session(atoi(argv[i]));
513 		} else {
514 			(void) fprintf(stderr,
515 			    gettext("Invalid argument %s\n"), argv[i]);
516 				continue;
517 		}
518 		if (ret == -1)
519 			(void) fprintf(stdout,
520 			    gettext("Session id %d not found.\n"),
521 			    atoi(argv[i]));
522 	}
523 	return (0);
524 }
525 
526 static int
527 ndmp_get_password(char **password)
528 {
529 	char *pw1, pw2[257];
530 	int i;
531 
532 	for (i = 0; i < NDMP_PASSWORD_RETRIES; i++) {
533 		/*
534 		 * getpassphrase use the same buffer to return password, so
535 		 * copy the result in different buffer, before calling the
536 		 * getpassphrase again.
537 		 */
538 		if ((pw1 =
539 		    getpassphrase(gettext("Enter new password: "))) != NULL) {
540 			(void) strlcpy(pw2, pw1, sizeof (pw2));
541 			if ((pw1 =
542 			    getpassphrase(gettext("Re-enter  password: ")))
543 			    != NULL) {
544 				if (strncmp(pw1, pw2, strlen(pw1)) == 0) {
545 					*password = pw1;
546 					return (0);
547 				} else {
548 					(void) fprintf(stderr,
549 					    gettext("Both password did not "
550 					    "match.\n"));
551 				}
552 			}
553 		}
554 	}
555 	return (-1);
556 }
557 
558 static int
559 ndmp_enable_auth(int argc, char **argv, ndmp_command_t *cur_cmd)
560 {
561 	char *auth_type, *username, *password;
562 	int c, i, auth_type_flag = 0;
563 	char *enc_password;
564 
565 	/* enable <-a auth-type> <-u username> */
566 	if (argc != 5) {
567 		usage(B_FALSE, cur_cmd);
568 	}
569 
570 	while ((c = getopt(argc, argv, ":a:u:")) != -1) {
571 		switch (c) {
572 		case 'a':
573 			auth_type = strdup(optarg);
574 			break;
575 		case 'u':
576 			username = strdup(optarg);
577 			break;
578 		case ':':
579 			(void) fprintf(stderr, gettext("Option -%c "
580 			    "requires an operand\n"), optopt);
581 			usage(B_FALSE, cur_cmd);
582 			break;
583 		case '?':
584 			(void) fprintf(stderr, gettext("Unrecognized "
585 			    "option: -%c\n"), optopt);
586 			usage(B_FALSE, cur_cmd);
587 		}
588 	}
589 
590 	if ((auth_type) && (username)) {
591 		if (ndmp_get_password(&password)) {
592 			(void) fprintf(stderr, gettext("Could not get correct "
593 			    "password, exiting..."));
594 			free(auth_type);
595 			free(username);
596 			exit(-1);
597 		}
598 	} else {
599 		(void) fprintf(stderr, gettext("%s or %s can not be blank"),
600 		    "'auth-type'", "'username'");
601 		free(auth_type);
602 		free(username);
603 		exit(-1);
604 	}
605 
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));
610 		free(auth_type);
611 		free(username);
612 		exit(-1);
613 	}
614 
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) {
618 			auth_type_flag = 1;
619 			if ((ndmp_set_prop((char *)ndmp_auth_table[i].username,
620 			    username)) == -1) {
621 				(void) fprintf(stdout,
622 				    gettext("Could not set username - %s\n"),
623 				    ndmp_strerror(ndmp_errno));
624 				continue;
625 			}
626 			if ((ndmp_set_prop((char *)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));
631 				continue;
632 			}
633 			if (!ndmp_door_status() &&
634 			    (ndmp_service_refresh()) == -1) {
635 				(void) fprintf(stdout,
636 				    gettext("Could not refesh ndmpd service "
637 				    "properties\n"));
638 			}
639 		}
640 	}
641 	free(auth_type);
642 	free(username);
643 	free(enc_password);
644 
645 	if (!auth_type_flag)
646 		usage(B_FALSE, cur_cmd);
647 
648 	return (0);
649 }
650 
651 static int
652 ndmp_disable_auth(int argc, char **argv, ndmp_command_t *cur_cmd)
653 {
654 	char *auth_type;
655 	int c, i, auth_type_flag = 0;
656 
657 	/* disable <-a auth-type> */
658 	if (argc != 3) {
659 		usage(B_FALSE, cur_cmd);
660 	}
661 
662 	while ((c = getopt(argc, argv, ":a:")) != -1) {
663 		switch (c) {
664 		case 'a':
665 			auth_type = strdup(optarg);
666 			break;
667 		case ':':
668 			(void) fprintf(stderr, gettext("Option -%c "
669 			    "requires an operand\n"), optopt);
670 			break;
671 		case '?':
672 			(void) fprintf(stderr, gettext("Unrecognized "
673 			    "option: -%c\n"), optopt);
674 		}
675 	}
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) {
679 			auth_type_flag = 1;
680 			if ((ndmp_set_prop((char *)ndmp_auth_table[i].username,
681 			    "")) == -1) {
682 				(void) fprintf(stdout,
683 				    gettext("Could not clear username - %s\n"),
684 				    ndmp_strerror(ndmp_errno));
685 				continue;
686 			}
687 			if ((ndmp_set_prop((char *)ndmp_auth_table[i].password,
688 			    "")) == -1) {
689 				(void) fprintf(stdout,
690 				    gettext("Could not clear password - %s\n"),
691 				    ndmp_strerror(ndmp_errno));
692 				continue;
693 			}
694 			if (!ndmp_door_status() &&
695 			    (ndmp_service_refresh()) == -1) {
696 				(void) fprintf(stdout, gettext("Could not "
697 				    "refesh ndmpd service properties\n"));
698 			}
699 		}
700 	}
701 	free(auth_type);
702 
703 	if (!auth_type_flag)
704 		usage(B_FALSE, cur_cmd);
705 
706 	return (0);
707 }
708 
709 int
710 main(int argc, char **argv)
711 {
712 	int ret;
713 	int i;
714 	char *cmdname;
715 	ndmp_command_t	*current_command = NULL;
716 
717 	(void) setlocale(LC_ALL, "");
718 	(void) textdomain(TEXT_DOMAIN);
719 
720 	opterr = 0;
721 
722 	/* Make sure the user has specified some command. */
723 	if (argc < 2) {
724 		(void) fprintf(stderr, gettext("Missing command.\n"));
725 		usage(B_FALSE, current_command);
726 	}
727 
728 	cmdname = argv[1];
729 
730 	/*
731 	 * Special case '-?'
732 	 */
733 	if (strcmp(cmdname, "-?") == 0)
734 		usage(B_TRUE, current_command);
735 
736 	/*
737 	 * Run the appropriate sub-command.
738 	 */
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,
743 			    current_command);
744 			break;
745 		}
746 	}
747 
748 	if (i == NCOMMAND) {
749 		(void) fprintf(stderr, gettext("Unrecognized "
750 		    "command '%s'\n"), cmdname);
751 		usage(B_FALSE, current_command);
752 	}
753 
754 	return (ret);
755 }
756