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