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