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