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