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
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.
13 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
17 * MS-compatible Directory Server Discovery API, DsGetDC...()
22 #include <smb/nterror.h>
23 #include <smb/ntstatus.h>
24 #include <arpa/inet.h>
29 #define DSGETDC_VALID_FLAGS ( \
30 DS_FORCE_REDISCOVERY | \
31 DS_DIRECTORY_SERVICE_REQUIRED | \
32 DS_DIRECTORY_SERVICE_PREFERRED | \
33 DS_GC_SERVER_REQUIRED | \
35 DS_BACKGROUND_ONLY | \
38 DS_TIMESERV_REQUIRED | \
39 DS_WRITABLE_REQUIRED | \
40 DS_GOOD_TIMESERV_PREFERRED | \
42 DS_ONLY_LDAP_NEEDED | \
45 DS_RETURN_FLAT_NAME | \
48 static struct timeval TIMEOUT
= { 15, 0 };
51 * The Windows version of this would return a single allocation,
52 * where any strings pointed to in the returned structure would be
53 * stored in space following the top-level returned structure.
54 * This allows NetApiBufferFree() to be the same as free().
56 * However, we don't have an easy way to do that right now, so
57 * the dcinfo returned here will be free'd with DsFreeDcInfo().
60 _DsGetDcName(const char *ComputerName
,
61 const char *DomainName
, const struct uuid
*DomainGuid
,
62 const char *SiteName
, uint32_t Flags
,
63 DOMAIN_CONTROLLER_INFO
**dcinfo
)
68 enum clnt_stat clstat
;
71 (void) memset(&args
, 0, sizeof (args
));
72 (void) memset(&res
, 0, sizeof (res
));
75 * Later check for over constrained optional args here,
76 * and return (ERROR_INVALID_PARAMETER);
79 if (Flags
& ~DSGETDC_VALID_FLAGS
)
80 return (ERROR_INVALID_FLAGS
);
83 * Call the ADS deamon.
85 clnt
= clnt_door_create(ADSPRIV_PROGRAM
, ADSPRIV_V1
, ADSPRIV_MAX_XFER
);
87 return (RPC_S_NOT_LISTENING
);
89 args
.ComputerName
= (char *)ComputerName
;
90 args
.DomainName
= (char *)DomainName
;
91 if (DomainGuid
!= NULL
)
92 (void) memcpy(&args
.DomainGuid
, DomainGuid
,
93 sizeof (args
.DomainGuid
));
94 args
.SiteName
= (char *)SiteName
;
97 clstat
= clnt_call(clnt
, ADSPRIV_GetDcName
,
98 (xdrproc_t
)xdr_DsGetDcNameArgs
, (caddr_t
)&args
,
99 (xdrproc_t
)xdr_DsGetDcNameRes
, (caddr_t
)&res
, TIMEOUT
);
102 if (clstat
!= RPC_SUCCESS
)
103 return (RPC_S_CALL_FAILED
);
107 *dcinfo
= malloc(sizeof (**dcinfo
));
109 return (ERROR_NOT_ENOUGH_MEMORY
);
112 * We have taken pains to make these two the same.
113 * DOMAIN_CONTROLLER_INFO / struct adspriv_dcinfo
115 /* LINTED E_TRUE_LOGICAL_EXPR */
116 assert(sizeof (**dcinfo
) == sizeof (res
.DsGetDcNameRes_u
.res0
));
117 (void) memcpy(*dcinfo
, &res
.DsGetDcNameRes_u
.res0
, sizeof (**dcinfo
));
120 * NB: Do NOT xdr_free the result, because we're
121 * returning a copy of it to the caller.
127 DsGetDcName(const char *ComputerName
,
128 const char *DomainName
, const struct uuid
*DomainGuid
,
129 const char *SiteName
, uint32_t Flags
,
130 DOMAIN_CONTROLLER_INFO
**dcinfo
)
135 status
= _DsGetDcName(ComputerName
, DomainName
, DomainGuid
,
136 SiteName
, Flags
, dcinfo
);
142 case NT_STATUS_NO_SUCH_DOMAIN
: /* Specified domain unknown */
143 case NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND
:
144 case NT_STATUS_CANT_WAIT
: /* or gave up waiting. */
145 case NT_STATUS_INVALID_SERVER_STATE
: /* not in domain mode. */
146 rc
= ERROR_NO_SUCH_DOMAIN
;
149 rc
= ERROR_INTERNAL_ERROR
;
156 DsFreeDcInfo(DOMAIN_CONTROLLER_INFO
*dci
)
159 xdr_free(xdr_DsGetDcNameRes
, (char *)dci
);