xref: /illumos-gate/usr/src/cmd/idmap/nltest/nltest.c (revision bbcfe1fdf407bba4db5c2e62a69b67be0c4cb443)
1b3700b07SGordon Ross /*
2b3700b07SGordon Ross  * This file and its contents are supplied under the terms of the
3b3700b07SGordon Ross  * Common Development and Distribution License ("CDDL"), version 1.0.
4b3700b07SGordon Ross  * You may only use this file in accordance with the terms of version
5b3700b07SGordon Ross  * 1.0 of the CDDL.
6b3700b07SGordon Ross  *
7b3700b07SGordon Ross  * A full copy of the text of the CDDL should have accompanied this
8b3700b07SGordon Ross  * source.  A copy of the CDDL is also available via the Internet at
9b3700b07SGordon Ross  * http://www.illumos.org/license/CDDL.
10b3700b07SGordon Ross  */
11b3700b07SGordon Ross 
12b3700b07SGordon Ross /*
13b3700b07SGordon Ross  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
14*bbcfe1fdSGordon Ross  * Copyright 2021 RackTop Systems, Inc.
15b3700b07SGordon Ross  */
16b3700b07SGordon Ross 
17b3700b07SGordon Ross 
18b3700b07SGordon Ross #include <stdio.h>
19b3700b07SGordon Ross #include <libintl.h>
20b3700b07SGordon Ross #include <stdlib.h>
21b3700b07SGordon Ross #include <strings.h>
22b3700b07SGordon Ross #include <err.h>
23b3700b07SGordon Ross #include <ads/dsgetdc.h>
24b3700b07SGordon Ross #include <smb/nterror.h>
25b3700b07SGordon Ross #include <uuid/uuid.h>
26b3700b07SGordon Ross 
27b3700b07SGordon Ross 
28b3700b07SGordon Ross static void dclist_usage(void);
29b3700b07SGordon Ross static int cmd_dclist(char *);
30b3700b07SGordon Ross static void dcname_usage(void);
31b3700b07SGordon Ross static int cmd_dcname(char *);
32b3700b07SGordon Ross static void dsgetdc_usage(void);
33b3700b07SGordon Ross static int cmd_dsgetdc(char *);
34b3700b07SGordon Ross static void dsgetdcname_usage(void);
35b3700b07SGordon Ross static int cmd_dsgetdcname(char *);
36b3700b07SGordon Ross static void kick_usage(void);
37b3700b07SGordon Ross static int cmd_kick(char *);
38b3700b07SGordon Ross static void help(void);
39b3700b07SGordon Ross 
40b3700b07SGordon Ross typedef int cmd_fn_t (char *);
41b3700b07SGordon Ross typedef void cmd_usage_t (void);
42b3700b07SGordon Ross 
43b3700b07SGordon Ross 
44b3700b07SGordon Ross static struct commands {
45b3700b07SGordon Ross 	const char	*name;	/* name of subcommand */
46b3700b07SGordon Ross 	cmd_fn_t	*fn;	/* pointer to subcommand handler function */
47b3700b07SGordon Ross 	cmd_usage_t	*usage;	/* pointer to subcommand help function */
48b3700b07SGordon Ross 	int		optreq; /* does this have a required optval */
49b3700b07SGordon Ross } commands[] = {
50b3700b07SGordon Ross 	{"dclist", cmd_dclist, dclist_usage, 0},
51b3700b07SGordon Ross 	{"dcname", cmd_dcname, dcname_usage, 0},
52b3700b07SGordon Ross 	{"dsgetdc", cmd_dsgetdc, dsgetdc_usage, 0},
53b3700b07SGordon Ross 	{"dsgetdcname", cmd_dsgetdcname, dsgetdcname_usage, 0},
54b3700b07SGordon Ross 	{"kick", cmd_kick, kick_usage, 0},
55b3700b07SGordon Ross 	{NULL, NULL, NULL, 0}
56b3700b07SGordon Ross };
57b3700b07SGordon Ross 
58b3700b07SGordon Ross 
59b3700b07SGordon Ross /*
60b3700b07SGordon Ross  * lookupcmd
61b3700b07SGordon Ross  */
62b3700b07SGordon Ross static struct commands *
lookupcmd(const char * name)63b3700b07SGordon Ross lookupcmd(const char *name)
64b3700b07SGordon Ross {
65b3700b07SGordon Ross 	struct commands *cmd;
66b3700b07SGordon Ross 
67b3700b07SGordon Ross 	for (cmd = commands; cmd->name; cmd++) {
68b3700b07SGordon Ross 		if (strcasecmp(cmd->name, name) == 0)
69b3700b07SGordon Ross 			return (cmd);
70b3700b07SGordon Ross 	}
71b3700b07SGordon Ross 	return (NULL);
72b3700b07SGordon Ross }
73b3700b07SGordon Ross 
74b3700b07SGordon Ross /*
75b3700b07SGordon Ross  * dclist
76b3700b07SGordon Ross  */
77b3700b07SGordon Ross static void
dclist_usage(void)78b3700b07SGordon Ross dclist_usage(void)
79b3700b07SGordon Ross {
80b3700b07SGordon Ross 	(void) printf(gettext("usage: nltest dclist... \n"));
81b3700b07SGordon Ross 	exit(1);
82b3700b07SGordon Ross }
83b3700b07SGordon Ross 
84b3700b07SGordon Ross /* ARGSUSED */
85b3700b07SGordon Ross static int
cmd_dclist(char * optval)86b3700b07SGordon Ross cmd_dclist(char *optval)
87b3700b07SGordon Ross {
88b3700b07SGordon Ross 	(void) printf("cmd_dclist() \n");
89b3700b07SGordon Ross 	return (0);
90b3700b07SGordon Ross }
91b3700b07SGordon Ross 
92b3700b07SGordon Ross /*
93b3700b07SGordon Ross  * dcname
94b3700b07SGordon Ross  */
95b3700b07SGordon Ross static void
dcname_usage(void)96b3700b07SGordon Ross dcname_usage(void)
97b3700b07SGordon Ross {
98b3700b07SGordon Ross 	(void) printf(gettext("usage: nltest dcname... \n"));
99b3700b07SGordon Ross 	exit(1);
100b3700b07SGordon Ross }
101b3700b07SGordon Ross 
102b3700b07SGordon Ross /* ARGSUSED */
103b3700b07SGordon Ross static int
cmd_dcname(char * optval)104b3700b07SGordon Ross cmd_dcname(char *optval)
105b3700b07SGordon Ross {
106b3700b07SGordon Ross 	(void) printf("cmd_dcname() \n");
107b3700b07SGordon Ross 	return (0);
108b3700b07SGordon Ross }
109b3700b07SGordon Ross 
110b3700b07SGordon Ross /*
111b3700b07SGordon Ross  * dsgetdc
112b3700b07SGordon Ross  */
113b3700b07SGordon Ross static void
dsgetdc_usage(void)114b3700b07SGordon Ross dsgetdc_usage(void)
115b3700b07SGordon Ross {
116b3700b07SGordon Ross 	(void) printf(gettext("usage: nltest dsgetdc... \n"));
117b3700b07SGordon Ross 	exit(1);
118b3700b07SGordon Ross }
119b3700b07SGordon Ross 
120b3700b07SGordon Ross /* ARGSUSED */
121b3700b07SGordon Ross static int
cmd_dsgetdc(char * optval)122b3700b07SGordon Ross cmd_dsgetdc(char *optval)
123b3700b07SGordon Ross {
124b3700b07SGordon Ross 	(void) printf("cmd_dsgetdc() \n");
125b3700b07SGordon Ross 	return (0);
126b3700b07SGordon Ross }
127b3700b07SGordon Ross 
128b3700b07SGordon Ross /*
129b3700b07SGordon Ross  * dsgetdcname
130b3700b07SGordon Ross  */
131b3700b07SGordon Ross static void
dsgetdcname_usage(void)132b3700b07SGordon Ross dsgetdcname_usage(void)
133b3700b07SGordon Ross {
134b3700b07SGordon Ross 	(void) printf(gettext("usage: nltest dsgetdcname domainname \n"));
135b3700b07SGordon Ross 	exit(1);
136b3700b07SGordon Ross }
137b3700b07SGordon Ross 
138b3700b07SGordon Ross static int
cmd_dsgetdcname(char * domname)139b3700b07SGordon Ross cmd_dsgetdcname(char *domname)
140b3700b07SGordon Ross {
141b3700b07SGordon Ross 	char uuid_buf[UUID_PRINTABLE_STRING_LENGTH];
142b3700b07SGordon Ross 	int err = 0;
143b3700b07SGordon Ross 	char *atype;
144b3700b07SGordon Ross 	DOMAIN_CONTROLLER_INFO *dcinfo;
145b3700b07SGordon Ross 
146b3700b07SGordon Ross 	if (domname != NULL)
147b3700b07SGordon Ross 		(void) printf("  Domain name supplied:  %s \n", domname);
148b3700b07SGordon Ross 
149b3700b07SGordon Ross 	err = DsGetDcName(NULL, domname, NULL, NULL, 0, &dcinfo);
150b3700b07SGordon Ross 
151b3700b07SGordon Ross 	switch (err) {
152b3700b07SGordon Ross 	case 0:
153b3700b07SGordon Ross 		break;
154b3700b07SGordon Ross 	case ERROR_NO_SUCH_DOMAIN:
155b3700b07SGordon Ross 		(void) printf("Domain controller not found.\n");
156b3700b07SGordon Ross 		(void) printf("See: /var/run/idmap/discovery.log\n");
157b3700b07SGordon Ross 		exit(1);
158b3700b07SGordon Ross 	default:
159b3700b07SGordon Ross 		(void) printf("Unexpected error %d\n", err);
160b3700b07SGordon Ross 		exit(1);
161b3700b07SGordon Ross 	}
162b3700b07SGordon Ross 
163b3700b07SGordon Ross 	switch (dcinfo->DomainControllerAddressType) {
164b3700b07SGordon Ross 	case DS_INET_ADDRESS:
165b3700b07SGordon Ross 		atype = "inet";
166b3700b07SGordon Ross 		break;
167b3700b07SGordon Ross 	case DS_NETBIOS_ADDRESS:
168b3700b07SGordon Ross 		atype = "netbios";
169b3700b07SGordon Ross 		break;
170b3700b07SGordon Ross 	default:
171b3700b07SGordon Ross 		atype = "?";
172b3700b07SGordon Ross 		break;
173b3700b07SGordon Ross 	}
174b3700b07SGordon Ross 
175b3700b07SGordon Ross 	uuid_unparse(dcinfo->DomainGuid, uuid_buf);
176b3700b07SGordon Ross 
177b3700b07SGordon Ross 	(void) printf("Data Returned from DsGetDcName() call: \n");
178b3700b07SGordon Ross 	(void) printf("  DC Name:  %s \n", dcinfo->DomainControllerName);
179b3700b07SGordon Ross 	(void) printf("  DC Addr:  %s \n", dcinfo->DomainControllerAddress);
180b3700b07SGordon Ross 	(void) printf("  DC Addr Type:  %s \n", atype);
181b3700b07SGordon Ross 	(void) printf("  Domain Name:  %s \n", dcinfo->DomainName);
182b3700b07SGordon Ross 	(void) printf("  Domain GUID:  %s \n", uuid_buf);
183b3700b07SGordon Ross 	(void) printf("  DNS Forest Name:  %s \n", dcinfo->DnsForestName);
184b3700b07SGordon Ross 	(void) printf("  Flags:  0x%x \n", dcinfo->Flags);
185b3700b07SGordon Ross 	(void) printf("  DC Site Name:  %s \n", dcinfo->DcSiteName);
186b3700b07SGordon Ross 	(void) printf("  Client Site Name:  %s \n", dcinfo->ClientSiteName);
187b3700b07SGordon Ross 
188*bbcfe1fdSGordon Ross 	DsFreeDcInfo(dcinfo);
189*bbcfe1fdSGordon Ross 
190b3700b07SGordon Ross 	return (0);
191b3700b07SGordon Ross }
192b3700b07SGordon Ross 
193b3700b07SGordon Ross /*
194b3700b07SGordon Ross  * kick
195b3700b07SGordon Ross  */
196b3700b07SGordon Ross static void
kick_usage(void)197b3700b07SGordon Ross kick_usage(void)
198b3700b07SGordon Ross {
199b3700b07SGordon Ross 	(void) printf(gettext("usage: nltest /KICK \n"));
200b3700b07SGordon Ross 	exit(1);
201b3700b07SGordon Ross }
202b3700b07SGordon Ross 
203b3700b07SGordon Ross 
204b3700b07SGordon Ross static int
cmd_kick(char * domname)205b3700b07SGordon Ross cmd_kick(char *domname)
206b3700b07SGordon Ross {
207b3700b07SGordon Ross 	int flags = 0;
208b3700b07SGordon Ross 	int result;
209b3700b07SGordon Ross 
210b3700b07SGordon Ross 	result = _DsForceRediscovery(domname, flags);
211b3700b07SGordon Ross 
212b3700b07SGordon Ross 	return (result);
213b3700b07SGordon Ross }
214b3700b07SGordon Ross 
215b3700b07SGordon Ross /*
216b3700b07SGordon Ross  * help functions
217b3700b07SGordon Ross  */
218b3700b07SGordon Ross 
219b3700b07SGordon Ross static void
help(void)220*bbcfe1fdSGordon Ross help(void)
221*bbcfe1fdSGordon Ross {
222b3700b07SGordon Ross 	(void) printf("\n");
223b3700b07SGordon Ross 	/*
224b3700b07SGordon Ross 	 * TODO: We may want to revise this help text.  It's basically
225b3700b07SGordon Ross 	 * a copy-paste from:
226b3700b07SGordon Ross 	 *   http://technet.microsoft.com/en-us/library/cc731935.aspx
227b3700b07SGordon Ross 	 */
228b3700b07SGordon Ross 	(void) printf(gettext("usage: %s /subcommand\n"),
229b3700b07SGordon Ross 	    (char *)getexecname());
230b3700b07SGordon Ross 	(void) printf(gettext("where subcommands are:\n"
231b3700b07SGordon Ross #if 0	/* not yet */
232b3700b07SGordon Ross 	    " dclist        Lists all domain controllers in the domain.\n"
233b3700b07SGordon Ross 	    " dcname        Lists the PDC or PDC emulator.\n"
234b3700b07SGordon Ross 	    " dsgetdc       Queries DNS server for list of DCs and"
235b3700b07SGordon Ross 	    " their IP addresses and contacts each DC to check"
236b3700b07SGordon Ross 	    " for connectivity.\n"
237b3700b07SGordon Ross #endif
238b3700b07SGordon Ross 	    " dsgetdcname   returns the name of a domain controller in a"
239b3700b07SGordon Ross 	    " specified domain\n"
240b3700b07SGordon Ross 	    " help          display help on specified subcommand\n"
241b3700b07SGordon Ross 	    " kick          trigger domain controller re-discovery\n"
242b3700b07SGordon Ross 	    "\n"));
243b3700b07SGordon Ross 	exit(1);
244b3700b07SGordon Ross }
245b3700b07SGordon Ross 
246b3700b07SGordon Ross int
main(int argc,char * argv[])247b3700b07SGordon Ross main(int argc, char *argv[])
248b3700b07SGordon Ross {
249b3700b07SGordon Ross 	struct commands *cmd;
250b3700b07SGordon Ross 	int err = 0;
251b3700b07SGordon Ross 	char *option_cmd = NULL;
252b3700b07SGordon Ross 	char *arg;
253b3700b07SGordon Ross 	char *p;
254b3700b07SGordon Ross 	char *optname;
255b3700b07SGordon Ross 	char *optval = NULL;
256b3700b07SGordon Ross 	int i;
257b3700b07SGordon Ross 	int optind = 1;
258b3700b07SGordon Ross 
259b3700b07SGordon Ross 	/*
260b3700b07SGordon Ross 	 * Parse options.
261b3700b07SGordon Ross 	 */
262b3700b07SGordon Ross 	while (optind < argc) {
263b3700b07SGordon Ross 		arg = argv[optind];
264b3700b07SGordon Ross 		optname = NULL;
265b3700b07SGordon Ross 		optval = NULL;
266b3700b07SGordon Ross 
267b3700b07SGordon Ross 		/* Is this an option? */
268b3700b07SGordon Ross 		if (arg[0] == '/') {
269b3700b07SGordon Ross 			optname = arg + 1;
270b3700b07SGordon Ross 			optind++;
271b3700b07SGordon Ross 
272b3700b07SGordon Ross 			/*
273b3700b07SGordon Ross 			 * May have  /optname:value
274b3700b07SGordon Ross 			 */
275b3700b07SGordon Ross 			if ((p = strchr(optname, ':')) != NULL) {
276b3700b07SGordon Ross 				*p++ = '\0';
277b3700b07SGordon Ross 				optval = p;
278b3700b07SGordon Ross 			}
279b3700b07SGordon Ross 		} else if (arg[0] == '-' && arg[1] == '-') {
280b3700b07SGordon Ross 			optname = arg + 2;
281b3700b07SGordon Ross 			optind++;
282b3700b07SGordon Ross 
283b3700b07SGordon Ross 			/*
284b3700b07SGordon Ross 			 * May have  --optname=value
285b3700b07SGordon Ross 			 */
286b3700b07SGordon Ross 			if ((p = strchr(optname, '=')) != NULL) {
287b3700b07SGordon Ross 				*p++ = '\0';
288b3700b07SGordon Ross 				optval = p;
289b3700b07SGordon Ross 			}
290b3700b07SGordon Ross 		} else {
291b3700b07SGordon Ross 			/* Not an option.  Stop parsing. */
292b3700b07SGordon Ross 			break;
293b3700b07SGordon Ross 		}
294b3700b07SGordon Ross 
295b3700b07SGordon Ross 		/*
296b3700b07SGordon Ross 		 * Handle each optname (and maybe its optval)
297b3700b07SGordon Ross 		 * Might put this logic in a table of options.
298b3700b07SGordon Ross 		 * (including a flag for "optval required",
299b3700b07SGordon Ross 		 * so that check could be factored out)
300b3700b07SGordon Ross 		 */
301b3700b07SGordon Ross 		for (cmd = commands; cmd->name; cmd++) {
302b3700b07SGordon Ross 			if (!strcasecmp(optname, cmd->name)) {
303b3700b07SGordon Ross 				/* cmd->name  requires an optval */
304b3700b07SGordon Ross 				if (optval == NULL && optind < argc)
305b3700b07SGordon Ross 					optval = argv[optind++];
306b3700b07SGordon Ross 
307b3700b07SGordon Ross 				if (optval == NULL && cmd->optreq > 0) {
308b3700b07SGordon Ross 					(void) fprintf(stderr,
309b3700b07SGordon Ross 					    "%s: option %s requires a value\n",
310b3700b07SGordon Ross 					    argv[0], optname);
311b3700b07SGordon Ross 					return (1);
312b3700b07SGordon Ross 				}
313b3700b07SGordon Ross 				option_cmd = optname;
314b3700b07SGordon Ross 			}
315b3700b07SGordon Ross 		}
316b3700b07SGordon Ross 	}
317b3700b07SGordon Ross 
318b3700b07SGordon Ross 	/*
319b3700b07SGordon Ross 	 * Handle remaining non-option arguments
320b3700b07SGordon Ross 	 */
321b3700b07SGordon Ross 	for (i = optind; i < argc; i++) {
322b3700b07SGordon Ross 		(void) printf("arg: %s\n", argv[i]);
323b3700b07SGordon Ross 	}
324b3700b07SGordon Ross 
325b3700b07SGordon Ross 	if (option_cmd == NULL)
326b3700b07SGordon Ross 		help();
327b3700b07SGordon Ross 
328b3700b07SGordon Ross 	cmd = lookupcmd(option_cmd);
329b3700b07SGordon Ross 	if (cmd == NULL)
330b3700b07SGordon Ross 		err = 1;
331b3700b07SGordon Ross 	else
332b3700b07SGordon Ross 		err = cmd->fn(optval);
333b3700b07SGordon Ross 
334b3700b07SGordon Ross 	return (err);
335b3700b07SGordon Ross }
336