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 * 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 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 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 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 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 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 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 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 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 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 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 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 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