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