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 <stdlib.h> 19*b3700b07SGordon Ross #include <stdarg.h> 20*b3700b07SGordon Ross #include <string.h> 21*b3700b07SGordon Ross #include <syslog.h> 22*b3700b07SGordon Ross #include <rpc/rpc.h> 23*b3700b07SGordon Ross #include <sys/uuid.h> 24*b3700b07SGordon Ross #include <smb/ntstatus.h> 25*b3700b07SGordon Ross #include <synch.h> 26*b3700b07SGordon Ross #include <thread.h> 27*b3700b07SGordon Ross #include <arpa/inet.h> 28*b3700b07SGordon Ross #include <uuid/uuid.h> 29*b3700b07SGordon Ross 30*b3700b07SGordon Ross #include "idmapd.h" 31*b3700b07SGordon Ross #include "libadutils.h" 32*b3700b07SGordon Ross #include "dsgetdc.h" 33*b3700b07SGordon Ross #include "ads_priv.h" 34*b3700b07SGordon Ross 35*b3700b07SGordon Ross void adspriv_program_1(struct svc_req *, register SVCXPRT *); 36*b3700b07SGordon Ross 37*b3700b07SGordon Ross SVCXPRT *dcl_xprt = NULL; 38*b3700b07SGordon Ross 39*b3700b07SGordon Ross void 40*b3700b07SGordon Ross init_dc_locator(void) 41*b3700b07SGordon Ross { 42*b3700b07SGordon Ross int connmaxrec = 32 * 1024; 43*b3700b07SGordon Ross 44*b3700b07SGordon Ross dcl_xprt = svc_door_create(adspriv_program_1, 45*b3700b07SGordon Ross ADSPRIV_PROGRAM, ADSPRIV_V1, connmaxrec); 46*b3700b07SGordon Ross if (dcl_xprt == NULL) { 47*b3700b07SGordon Ross syslog(LOG_ERR, "unable to create door RPC service"); 48*b3700b07SGordon Ross return; 49*b3700b07SGordon Ross } 50*b3700b07SGordon Ross 51*b3700b07SGordon Ross if (!svc_control(dcl_xprt, SVCSET_CONNMAXREC, &connmaxrec)) { 52*b3700b07SGordon Ross syslog(LOG_ERR, "unable to limit RPC request size"); 53*b3700b07SGordon Ross } 54*b3700b07SGordon Ross } 55*b3700b07SGordon Ross 56*b3700b07SGordon Ross void 57*b3700b07SGordon Ross fini_dc_locator(void) 58*b3700b07SGordon Ross { 59*b3700b07SGordon Ross if (dcl_xprt != NULL) 60*b3700b07SGordon Ross svc_destroy(dcl_xprt); 61*b3700b07SGordon Ross } 62*b3700b07SGordon Ross 63*b3700b07SGordon Ross /* 64*b3700b07SGordon Ross * Functions called by the (generated) adspriv_srv.c 65*b3700b07SGordon Ross */ 66*b3700b07SGordon Ross 67*b3700b07SGordon Ross /* ARGSUSED */ 68*b3700b07SGordon Ross bool_t 69*b3700b07SGordon Ross adspriv_null_1_svc(void *result, struct svc_req *rqstp) 70*b3700b07SGordon Ross { 71*b3700b07SGordon Ross return (TRUE); 72*b3700b07SGordon Ross } 73*b3700b07SGordon Ross 74*b3700b07SGordon Ross /* ARGSUSED */ 75*b3700b07SGordon Ross bool_t 76*b3700b07SGordon Ross adspriv_forcerediscovery_1_svc( 77*b3700b07SGordon Ross DsForceRediscoveryArgs args, 78*b3700b07SGordon Ross int *res, 79*b3700b07SGordon Ross struct svc_req *sreq) 80*b3700b07SGordon Ross { 81*b3700b07SGordon Ross /* Ignoring args for now. */ 82*b3700b07SGordon Ross 83*b3700b07SGordon Ross idmap_cfg_force_rediscovery(); 84*b3700b07SGordon Ross *res = 0; 85*b3700b07SGordon Ross 86*b3700b07SGordon Ross return (TRUE); 87*b3700b07SGordon Ross } 88*b3700b07SGordon Ross 89*b3700b07SGordon Ross 90*b3700b07SGordon Ross /* ARGSUSED */ 91*b3700b07SGordon Ross bool_t 92*b3700b07SGordon Ross adspriv_getdcname_1_svc( 93*b3700b07SGordon Ross DsGetDcNameArgs args, 94*b3700b07SGordon Ross DsGetDcNameRes *res, 95*b3700b07SGordon Ross struct svc_req *sreq) 96*b3700b07SGordon Ross { 97*b3700b07SGordon Ross uuid_t uuid; 98*b3700b07SGordon Ross adspriv_dcinfo *dci; 99*b3700b07SGordon Ross idmap_pg_config_t *pgcfg; 100*b3700b07SGordon Ross ad_disc_ds_t *ds; 101*b3700b07SGordon Ross char *s; 102*b3700b07SGordon Ross 103*b3700b07SGordon Ross /* Init */ 104*b3700b07SGordon Ross (void) memset(res, 0, sizeof (*res)); 105*b3700b07SGordon Ross res->status = 0; 106*b3700b07SGordon Ross dci = &res->DsGetDcNameRes_u.res0; 107*b3700b07SGordon Ross 108*b3700b07SGordon Ross if (args.Flags & DS_FORCE_REDISCOVERY) 109*b3700b07SGordon Ross idmap_cfg_force_rediscovery(); 110*b3700b07SGordon Ross 111*b3700b07SGordon Ross /* 112*b3700b07SGordon Ross * We normally should wait if discovery is running. 113*b3700b07SGordon Ross * Sort of mis-using the background flag as a way to 114*b3700b07SGordon Ross * skip the wait, until we really do background disc. 115*b3700b07SGordon Ross */ 116*b3700b07SGordon Ross if ((args.Flags & DS_BACKGROUND_ONLY) == 0) { 117*b3700b07SGordon Ross timespec_t tv = { 15, 0 }; 118*b3700b07SGordon Ross int rc = 0; 119*b3700b07SGordon Ross int waited = 0; 120*b3700b07SGordon Ross 121*b3700b07SGordon Ross (void) mutex_lock(&_idmapdstate.addisc_lk); 122*b3700b07SGordon Ross 123*b3700b07SGordon Ross if (_idmapdstate.addisc_st != 0) 124*b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "getdcname wait begin"); 125*b3700b07SGordon Ross 126*b3700b07SGordon Ross while (_idmapdstate.addisc_st != 0) { 127*b3700b07SGordon Ross waited++; 128*b3700b07SGordon Ross rc = cond_reltimedwait(&_idmapdstate.addisc_cv, 129*b3700b07SGordon Ross &_idmapdstate.addisc_lk, &tv); 130*b3700b07SGordon Ross if (rc == ETIME) 131*b3700b07SGordon Ross break; 132*b3700b07SGordon Ross } 133*b3700b07SGordon Ross (void) mutex_unlock(&_idmapdstate.addisc_lk); 134*b3700b07SGordon Ross 135*b3700b07SGordon Ross if (rc == ETIME) { 136*b3700b07SGordon Ross /* Caller will replace this with DC not found. */ 137*b3700b07SGordon Ross idmapdlog(LOG_ERR, "getdcname timeout"); 138*b3700b07SGordon Ross res->status = NT_STATUS_CANT_WAIT; 139*b3700b07SGordon Ross return (TRUE); 140*b3700b07SGordon Ross } 141*b3700b07SGordon Ross if (waited) { 142*b3700b07SGordon Ross idmapdlog(LOG_DEBUG, "getdcname wait done"); 143*b3700b07SGordon Ross } 144*b3700b07SGordon Ross } 145*b3700b07SGordon Ross 146*b3700b07SGordon Ross RDLOCK_CONFIG(); 147*b3700b07SGordon Ross pgcfg = &_idmapdstate.cfg->pgcfg; 148*b3700b07SGordon Ross 149*b3700b07SGordon Ross if (pgcfg->domain_name == NULL) { 150*b3700b07SGordon Ross res->status = NT_STATUS_INVALID_SERVER_STATE; 151*b3700b07SGordon Ross goto out; 152*b3700b07SGordon Ross } 153*b3700b07SGordon Ross 154*b3700b07SGordon Ross if (args.DomainName != NULL && args.DomainName[0] != '\0' && 155*b3700b07SGordon Ross 0 != strcasecmp(args.DomainName, pgcfg->domain_name)) { 156*b3700b07SGordon Ross /* 157*b3700b07SGordon Ross * They asked for a specific domain not our primary, 158*b3700b07SGordon Ross * which is not supported (and not needed). 159*b3700b07SGordon Ross */ 160*b3700b07SGordon Ross res->status = NT_STATUS_NO_SUCH_DOMAIN; 161*b3700b07SGordon Ross goto out; 162*b3700b07SGordon Ross } 163*b3700b07SGordon Ross 164*b3700b07SGordon Ross if ((ds = pgcfg->domain_controller) == NULL) { 165*b3700b07SGordon Ross res->status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; 166*b3700b07SGordon Ross goto out; 167*b3700b07SGordon Ross } 168*b3700b07SGordon Ross 169*b3700b07SGordon Ross dci->dci_DcName = strdup(ds->host); 170*b3700b07SGordon Ross 171*b3700b07SGordon Ross dci->dci_DcAddr = calloc(1, INET6_ADDRSTRLEN); 172*b3700b07SGordon Ross if (dci->dci_DcAddr != NULL && 173*b3700b07SGordon Ross ad_disc_getnameinfo(dci->dci_DcAddr, INET6_ADDRSTRLEN, 174*b3700b07SGordon Ross &ds->addr) == 0) 175*b3700b07SGordon Ross dci->dci_AddrType = DS_INET_ADDRESS; 176*b3700b07SGordon Ross 177*b3700b07SGordon Ross if ((s = pgcfg->domain_guid) != NULL && 178*b3700b07SGordon Ross 0 == uuid_parse(s, uuid)) { 179*b3700b07SGordon Ross (void) memcpy(dci->dci_guid, uuid, sizeof (uuid)); 180*b3700b07SGordon Ross } 181*b3700b07SGordon Ross 182*b3700b07SGordon Ross if ((s = pgcfg->domain_name) != NULL) 183*b3700b07SGordon Ross dci->dci_DomainName = strdup(s); 184*b3700b07SGordon Ross 185*b3700b07SGordon Ross if ((s = pgcfg->forest_name) != NULL) 186*b3700b07SGordon Ross dci->dci_DnsForestName = strdup(s); 187*b3700b07SGordon Ross 188*b3700b07SGordon Ross dci->dci_Flags = ds->flags; 189*b3700b07SGordon Ross dci->dci_DcSiteName = strdup(ds->site); 190*b3700b07SGordon Ross 191*b3700b07SGordon Ross if ((s = pgcfg->site_name) != NULL) 192*b3700b07SGordon Ross dci->dci_ClientSiteName = strdup(s); 193*b3700b07SGordon Ross 194*b3700b07SGordon Ross /* Address in binary form too. */ 195*b3700b07SGordon Ross (void) memcpy(&dci->dci_sockaddr, 196*b3700b07SGordon Ross &ds->addr, ADSPRIV_SOCKADDR_LEN); 197*b3700b07SGordon Ross 198*b3700b07SGordon Ross out: 199*b3700b07SGordon Ross UNLOCK_CONFIG(); 200*b3700b07SGordon Ross 201*b3700b07SGordon Ross return (TRUE); 202*b3700b07SGordon Ross } 203*b3700b07SGordon Ross 204*b3700b07SGordon Ross /* ARGSUSED */ 205*b3700b07SGordon Ross int 206*b3700b07SGordon Ross adspriv_program_1_freeresult(SVCXPRT *xprt, xdrproc_t fun, caddr_t res) 207*b3700b07SGordon Ross { 208*b3700b07SGordon Ross (void) xdr_free(fun, res); 209*b3700b07SGordon Ross return (TRUE); 210*b3700b07SGordon Ross } 211