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