98e935ca991ee3b8791014489806bbf996333680
[ddiss/samba.git] / source4 / rpc_server / dnsserver / dcerpc_dnsserver.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    DNS Server
5
6    Copyright (C) Amitay Isaacs 2011
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "talloc.h"
24 #include "rpc_server/dcerpc_server.h"
25 #include "dsdb/samdb/samdb.h"
26 #include "lib/util/dlinklist.h"
27 #include "librpc/gen_ndr/ndr_dnsserver.h"
28 #include "dnsserver.h"
29 #include "lib/ldb/include/ldb_private.h"
30
31 struct dnsserver_state {
32         struct loadparm_context *lp_ctx;
33         struct ldb_context *samdb;
34         struct dnsserver_zone *zones;
35         int zones_count;
36         struct dnsserver_serverinfo *serverinfo;
37 };
38
39
40 /* Utility functions */
41
42 static struct dnsserver_state *dnsserver_connect(struct dcesrv_call_state *dce_call)
43 {
44         struct dnsserver_state *dsstate;
45         struct dnsserver_zone *zones, *z;
46
47         dsstate = talloc_get_type(dce_call->context->private_data, struct dnsserver_state);
48         if (dsstate != NULL) {
49                 return dsstate;
50         }
51
52         dsstate = talloc_zero(dce_call->context, struct dnsserver_state);
53         if (dsstate == NULL) {
54                 return NULL;
55         }
56
57         dsstate->lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
58
59         /* FIXME: create correct auth_session_info for connecting user */
60         dsstate->samdb = samdb_connect(dsstate, dce_call->event_ctx, dsstate->lp_ctx,
61                                 dce_call->conn->auth_state.session_info, 0);
62         if (dsstate->samdb == NULL) {
63                 DEBUG(0,("dnsserver: Failed to open samdb"));
64                 goto failed;
65         }
66
67         /* Initialize server info */
68         dsstate->serverinfo = dnsserver_init_serverinfo(dsstate,
69                                                         dsstate->lp_ctx,
70                                                         dsstate->samdb);
71         if (dsstate->serverinfo == NULL) {
72                 goto failed;
73         }
74
75         /* Search for DNS zones */
76         zones = dnsserver_db_enumerate_zones(dsstate, dsstate->samdb, true);
77         if (zones == NULL) {
78                 goto failed;
79         }
80         for (z = zones; z; z = z->next) {
81                 z->zoneinfo = dnsserver_init_zoneinfo(z, dsstate->serverinfo, true);
82                 if (z->zoneinfo == NULL) {
83                         goto failed;
84                 }
85                 DLIST_ADD_END(dsstate->zones, z, NULL);
86                 dsstate->zones_count++;
87         }
88
89         zones = dnsserver_db_enumerate_zones(dsstate, dsstate->samdb, false);
90         if (zones == NULL) {
91                 goto failed;
92         }
93         for (z = zones; z; z = z->next) {
94                 z->zoneinfo = dnsserver_init_zoneinfo(z, dsstate->serverinfo, false);
95                 if (z->zoneinfo == NULL) {
96                         goto failed;
97                 }
98                 DLIST_ADD_END(dsstate->zones, z, NULL);
99                 dsstate->zones_count++;
100         }
101
102         dce_call->context->private_data = dsstate;
103
104         return dsstate;
105
106 failed:
107         talloc_free(dsstate);
108         dsstate = NULL;
109         return NULL;
110 }
111
112
113 /* dnsserver query functions */
114
115 /* [MS-DNSP].pdf Section 3.1.1.1 DNS Server Configuration Information */
116 static WERROR dnsserver_query_server(struct dnsserver_state *dsstate,
117                                         TALLOC_CTX *mem_ctx,
118                                         const char *operation,
119                                         const unsigned int client_version,
120                                         enum DNS_RPC_TYPEID *typeid,
121                                         union DNSSRV_RPC_UNION *r)
122 {
123         uint8_t is_integer, is_addresses, is_string, is_wstring, is_stringlist;
124         uint32_t answer_integer;
125         struct IP4_ARRAY *answer_iparray;
126         struct DNS_ADDR_ARRAY *answer_addrarray;
127         char *answer_string;
128         struct DNS_RPC_UTF8_STRING_LIST *answer_stringlist;
129         struct dnsserver_serverinfo *serverinfo;
130
131         serverinfo = dsstate->serverinfo;
132
133         if (strcasecmp(operation, "ServerInfo") == 0) {
134                 if (client_version == DNS_CLIENT_VERSION_W2K) {
135                         *typeid = DNSSRV_TYPEID_SERVER_INFO_W2K;
136                         r->ServerInfoW2K = talloc_zero(mem_ctx, struct DNS_RPC_SERVER_INFO_W2K);
137
138                         r->ServerInfoW2K->dwVersion = serverinfo->dwVersion;
139                         r->ServerInfoW2K->fBootMethod = serverinfo->fBootMethod;
140                         r->ServerInfoW2K->fAdminConfigured = serverinfo->fAdminConfigured;
141                         r->ServerInfoW2K->fAllowUpdate = serverinfo->fAllowUpdate;
142                         r->ServerInfoW2K->fDsAvailable = serverinfo->fDsAvailable;
143                         r->ServerInfoW2K->pszServerName = talloc_strdup(mem_ctx, serverinfo->pszServerName);
144                         r->ServerInfoW2K->pszDsContainer = talloc_strdup(mem_ctx, serverinfo->pszDsContainer);
145                         r->ServerInfoW2K->aipServerAddrs = ip4_array_copy(mem_ctx, serverinfo->aipServerAddrs);
146                         r->ServerInfoW2K->aipListenAddrs = ip4_array_copy(mem_ctx, serverinfo->aipListenAddrs);
147                         r->ServerInfoW2K->aipForwarders = ip4_array_copy(mem_ctx, serverinfo->aipForwarders);
148                         r->ServerInfoW2K->dwLogLevel = serverinfo->dwLogLevel;
149                         r->ServerInfoW2K->dwDebugLevel = serverinfo->dwDebugLevel;
150                         r->ServerInfoW2K->dwForwardTimeout = serverinfo->dwForwardTimeout;
151                         r->ServerInfoW2K->dwRpcProtocol = serverinfo->dwRpcProtocol;
152                         r->ServerInfoW2K->dwNameCheckFlag = serverinfo->dwNameCheckFlag;
153                         r->ServerInfoW2K->cAddressAnswerLimit = serverinfo->cAddressAnswerLimit;
154                         r->ServerInfoW2K->dwRecursionRetry = serverinfo->dwRecursionRetry;
155                         r->ServerInfoW2K->dwRecursionTimeout = serverinfo->dwRecursionTimeout;
156                         r->ServerInfoW2K->dwMaxCacheTtl = serverinfo->dwMaxCacheTtl;
157                         r->ServerInfoW2K->dwDsPollingInterval = serverinfo->dwDsPollingInterval;
158                         r->ServerInfoW2K->dwScavengingInterval = serverinfo->dwScavengingInterval;
159                         r->ServerInfoW2K->dwDefaultRefreshInterval = serverinfo->dwDefaultRefreshInterval;
160                         r->ServerInfoW2K->dwDefaultNoRefreshInterval = serverinfo->dwDefaultNoRefreshInterval;
161                         r->ServerInfoW2K->fAutoReverseZones = serverinfo->fAutoReverseZones;
162                         r->ServerInfoW2K->fAutoCacheUpdate = serverinfo->fAutoCacheUpdate;
163                         r->ServerInfoW2K->fRecurseAfterForwarding = serverinfo->fRecurseAfterForwarding;
164                         r->ServerInfoW2K->fForwardDelegations = serverinfo->fForwardDelegations;
165                         r->ServerInfoW2K->fNoRecursion = serverinfo->fNoRecursion;
166                         r->ServerInfoW2K->fSecureResponses = serverinfo->fSecureResponses;
167                         r->ServerInfoW2K->fRoundRobin = serverinfo->fRoundRobin;
168                         r->ServerInfoW2K->fLocalNetPriority = serverinfo->fLocalNetPriority;
169                         r->ServerInfoW2K->fBindSecondaries = serverinfo->fBindSecondaries;
170                         r->ServerInfoW2K->fWriteAuthorityNs = serverinfo->fWriteAuthorityNs;
171                         r->ServerInfoW2K->fStrictFileParsing = serverinfo->fStrictFileParsing;
172                         r->ServerInfoW2K->fLooseWildcarding = serverinfo->fLooseWildcarding;
173                         r->ServerInfoW2K->fDefaultAgingState = serverinfo->fDefaultAgingState;
174
175                 } else if (client_version == DNS_CLIENT_VERSION_DOTNET) {
176                         *typeid = DNSSRV_TYPEID_SERVER_INFO_DOTNET;
177                         r->ServerInfoDotNet = talloc_zero(mem_ctx, struct DNS_RPC_SERVER_INFO_DOTNET);
178
179                         r->ServerInfoDotNet->dwRpcStructureVersion = 0x01;
180                         r->ServerInfoDotNet->dwVersion = serverinfo->dwVersion;
181                         r->ServerInfoDotNet->fBootMethod = serverinfo->fBootMethod;
182                         r->ServerInfoDotNet->fAdminConfigured = serverinfo->fAdminConfigured;
183                         r->ServerInfoDotNet->fAllowUpdate = serverinfo->fAllowUpdate;
184                         r->ServerInfoDotNet->fDsAvailable = serverinfo->fDsAvailable;
185                         r->ServerInfoDotNet->pszServerName = talloc_strdup(mem_ctx, serverinfo->pszServerName);
186                         r->ServerInfoDotNet->pszDsContainer = talloc_strdup(mem_ctx, serverinfo->pszDsContainer);
187                         r->ServerInfoDotNet->aipServerAddrs = ip4_array_copy(mem_ctx, serverinfo->aipServerAddrs);
188                         r->ServerInfoDotNet->aipListenAddrs = ip4_array_copy(mem_ctx, serverinfo->aipListenAddrs);
189                         r->ServerInfoDotNet->aipForwarders = ip4_array_copy(mem_ctx, serverinfo->aipForwarders);
190                         r->ServerInfoDotNet->aipLogFilter = ip4_array_copy(mem_ctx, serverinfo->aipLogFilter);
191                         r->ServerInfoDotNet->pwszLogFilePath = talloc_strdup(mem_ctx, serverinfo->pwszLogFilePath);
192                         r->ServerInfoDotNet->pszDomainName = talloc_strdup(mem_ctx, serverinfo->pszDomainName);
193                         r->ServerInfoDotNet->pszForestName = talloc_strdup(mem_ctx, serverinfo->pszForestName);
194                         r->ServerInfoDotNet->pszDomainDirectoryPartition = talloc_strdup(mem_ctx, serverinfo->pszDomainDirectoryPartition);
195                         r->ServerInfoDotNet->pszForestDirectoryPartition = talloc_strdup(mem_ctx, serverinfo->pszForestDirectoryPartition);
196                         r->ServerInfoDotNet->dwLogLevel = serverinfo->dwLogLevel;
197                         r->ServerInfoDotNet->dwDebugLevel = serverinfo->dwDebugLevel;
198                         r->ServerInfoDotNet->dwForwardTimeout = serverinfo->dwForwardTimeout;
199                         r->ServerInfoDotNet->dwRpcProtocol = serverinfo->dwRpcProtocol;
200                         r->ServerInfoDotNet->dwNameCheckFlag = serverinfo->dwNameCheckFlag;
201                         r->ServerInfoDotNet->cAddressAnswerLimit = serverinfo->cAddressAnswerLimit;
202                         r->ServerInfoDotNet->dwRecursionRetry = serverinfo->dwRecursionRetry;
203                         r->ServerInfoDotNet->dwRecursionTimeout = serverinfo->dwRecursionTimeout;
204                         r->ServerInfoDotNet->dwMaxCacheTtl = serverinfo->dwMaxCacheTtl;
205                         r->ServerInfoDotNet->dwDsPollingInterval = serverinfo->dwDsPollingInterval;
206                         r->ServerInfoDotNet->dwLocalNetPriorityNetMask = serverinfo->dwLocalNetPriorityNetMask;
207                         r->ServerInfoDotNet->dwScavengingInterval = serverinfo->dwScavengingInterval;
208                         r->ServerInfoDotNet->dwDefaultRefreshInterval = serverinfo->dwDefaultRefreshInterval;
209                         r->ServerInfoDotNet->dwDefaultNoRefreshInterval = serverinfo->dwDefaultNoRefreshInterval;
210                         r->ServerInfoDotNet->dwLastScavengeTime = serverinfo->dwLastScavengeTime;
211                         r->ServerInfoDotNet->dwEventLogLevel = serverinfo->dwEventLogLevel;
212                         r->ServerInfoDotNet->dwLogFileMaxSize = serverinfo->dwLogFileMaxSize;
213                         r->ServerInfoDotNet->dwDsForestVersion = serverinfo->dwDsForestVersion;
214                         r->ServerInfoDotNet->dwDsDomainVersion = serverinfo->dwDsDomainVersion;
215                         r->ServerInfoDotNet->dwDsDsaVersion = serverinfo->dwDsDsaVersion;
216                         r->ServerInfoDotNet->fAutoReverseZones = serverinfo->fAutoReverseZones;
217                         r->ServerInfoDotNet->fAutoCacheUpdate = serverinfo->fAutoCacheUpdate;
218                         r->ServerInfoDotNet->fRecurseAfterForwarding = serverinfo->fRecurseAfterForwarding;
219                         r->ServerInfoDotNet->fForwardDelegations = serverinfo->fForwardDelegations;
220                         r->ServerInfoDotNet->fNoRecursion = serverinfo->fNoRecursion;
221                         r->ServerInfoDotNet->fSecureResponses = serverinfo->fSecureResponses;
222                         r->ServerInfoDotNet->fRoundRobin = serverinfo->fRoundRobin;
223                         r->ServerInfoDotNet->fLocalNetPriority = serverinfo->fLocalNetPriority;
224                         r->ServerInfoDotNet->fBindSecondaries = serverinfo->fBindSecondaries;
225                         r->ServerInfoDotNet->fWriteAuthorityNs = serverinfo->fWriteAuthorityNs;
226                         r->ServerInfoDotNet->fStrictFileParsing = serverinfo->fStrictFileParsing;
227                         r->ServerInfoDotNet->fLooseWildcarding = serverinfo->fLooseWildcarding;
228                         r->ServerInfoDotNet->fDefaultAgingState = serverinfo->fDefaultAgingState;
229
230                 } else if (client_version == DNS_CLIENT_VERSION_LONGHORN) {
231                         *typeid = DNSSRV_TYPEID_SERVER_INFO;
232                         r->ServerInfo = talloc_zero(mem_ctx, struct DNS_RPC_SERVER_INFO_LONGHORN);
233
234                         r->ServerInfo->dwRpcStructureVersion = 0x02;
235                         r->ServerInfo->dwVersion = serverinfo->dwVersion;
236                         r->ServerInfo->fBootMethod = serverinfo->fBootMethod;
237                         r->ServerInfo->fAdminConfigured = serverinfo->fAdminConfigured;
238                         r->ServerInfo->fAllowUpdate = serverinfo->fAllowUpdate;
239                         r->ServerInfo->fDsAvailable = serverinfo->fDsAvailable;
240                         r->ServerInfo->pszServerName = talloc_strdup(mem_ctx, serverinfo->pszServerName);
241                         r->ServerInfo->pszDsContainer = talloc_strdup(mem_ctx, serverinfo->pszDsContainer);
242                         r->ServerInfo->aipServerAddrs = ip4_array_to_dns_addr_array(mem_ctx, serverinfo->aipServerAddrs);
243                         r->ServerInfo->aipListenAddrs = ip4_array_to_dns_addr_array(mem_ctx, serverinfo->aipListenAddrs);
244                         r->ServerInfo->aipForwarders = ip4_array_to_dns_addr_array(mem_ctx, serverinfo->aipForwarders);
245                         r->ServerInfo->aipLogFilter = ip4_array_to_dns_addr_array(mem_ctx, serverinfo->aipLogFilter);
246                         r->ServerInfo->pwszLogFilePath = talloc_strdup(mem_ctx, serverinfo->pwszLogFilePath);
247                         r->ServerInfo->pszDomainName = talloc_strdup(mem_ctx, serverinfo->pszDomainName);
248                         r->ServerInfo->pszForestName = talloc_strdup(mem_ctx, serverinfo->pszForestName);
249                         r->ServerInfo->pszDomainDirectoryPartition = talloc_strdup(mem_ctx, serverinfo->pszDomainDirectoryPartition);
250                         r->ServerInfo->pszForestDirectoryPartition = talloc_strdup(mem_ctx, serverinfo->pszForestDirectoryPartition);
251                         r->ServerInfo->dwLogLevel = serverinfo->dwLogLevel;
252                         r->ServerInfo->dwDebugLevel = serverinfo->dwDebugLevel;
253                         r->ServerInfo->dwForwardTimeout = serverinfo->dwForwardTimeout;
254                         r->ServerInfo->dwRpcProtocol = serverinfo->dwRpcProtocol;
255                         r->ServerInfo->dwNameCheckFlag = serverinfo->dwNameCheckFlag;
256                         r->ServerInfo->cAddressAnswerLimit = serverinfo->cAddressAnswerLimit;
257                         r->ServerInfo->dwRecursionRetry = serverinfo->dwRecursionRetry;
258                         r->ServerInfo->dwRecursionTimeout = serverinfo->dwRecursionTimeout;
259                         r->ServerInfo->dwMaxCacheTtl = serverinfo->dwMaxCacheTtl;
260                         r->ServerInfo->dwDsPollingInterval = serverinfo->dwDsPollingInterval;
261                         r->ServerInfo->dwLocalNetPriorityNetMask = serverinfo->dwLocalNetPriorityNetMask;
262                         r->ServerInfo->dwScavengingInterval = serverinfo->dwScavengingInterval;
263                         r->ServerInfo->dwDefaultRefreshInterval = serverinfo->dwDefaultRefreshInterval;
264                         r->ServerInfo->dwDefaultNoRefreshInterval = serverinfo->dwDefaultNoRefreshInterval;
265                         r->ServerInfo->dwLastScavengeTime = serverinfo->dwLastScavengeTime;
266                         r->ServerInfo->dwEventLogLevel = serverinfo->dwEventLogLevel;
267                         r->ServerInfo->dwLogFileMaxSize = serverinfo->dwLogFileMaxSize;
268                         r->ServerInfo->dwDsForestVersion = serverinfo->dwDsForestVersion;
269                         r->ServerInfo->dwDsDomainVersion = serverinfo->dwDsDomainVersion;
270                         r->ServerInfo->dwDsDsaVersion = serverinfo->dwDsDsaVersion;
271                         r->ServerInfo->fReadOnlyDC = serverinfo->fReadOnlyDC;
272                         r->ServerInfo->fAutoReverseZones = serverinfo->fAutoReverseZones;
273                         r->ServerInfo->fAutoCacheUpdate = serverinfo->fAutoCacheUpdate;
274                         r->ServerInfo->fRecurseAfterForwarding = serverinfo->fRecurseAfterForwarding;
275                         r->ServerInfo->fForwardDelegations = serverinfo->fForwardDelegations;
276                         r->ServerInfo->fNoRecursion = serverinfo->fNoRecursion;
277                         r->ServerInfo->fSecureResponses = serverinfo->fSecureResponses;
278                         r->ServerInfo->fRoundRobin = serverinfo->fRoundRobin;
279                         r->ServerInfo->fLocalNetPriority = serverinfo->fLocalNetPriority;
280                         r->ServerInfo->fBindSecondaries = serverinfo->fBindSecondaries;
281                         r->ServerInfo->fWriteAuthorityNs = serverinfo->fWriteAuthorityNs;
282                         r->ServerInfo->fStrictFileParsing = serverinfo->fStrictFileParsing;
283                         r->ServerInfo->fLooseWildcarding = serverinfo->fLooseWildcarding;
284                         r->ServerInfo->fDefaultAgingState = serverinfo->fDefaultAgingState;
285                 }
286                 return WERR_OK;
287         }
288
289         is_integer = 0;
290
291         if (strcasecmp(operation, "AddressAnswerLimit") == 0) {
292                 answer_integer = serverinfo->cAddressAnswerLimit;
293                 is_integer = 1;
294         } else if (strcasecmp(operation, "AdminConfigured") == 0) {
295                 answer_integer = serverinfo->fAdminConfigured;
296                 is_integer = 1;
297         } else if (strcasecmp(operation, "AllowCNAMEAtNS") == 0) {
298                 answer_integer = 0;
299                 is_integer = 1;
300         } else if (strcasecmp(operation, "AllowUpdate") == 0) {
301                 answer_integer = serverinfo->fAllowUpdate;
302                 is_integer = 1;
303         } else if (strcasecmp(operation, "AutoCacheUpdate") == 0) {
304                 answer_integer = serverinfo->fAutoCacheUpdate;
305                 is_integer = 1;
306         } else if (strcasecmp(operation, "AutoConfigFileZones") == 0) {
307                 answer_integer = 1;
308                 is_integer = 1;
309         } else if (strcasecmp(operation, "BindSecondaries") == 0) {
310                 answer_integer = serverinfo->fBindSecondaries;
311                 is_integer = 1;
312         } else if (strcasecmp(operation, "BootMethod") == 0) {
313                 answer_integer = serverinfo->fBootMethod;
314                 is_integer = 1;
315         } else if (strcasecmp(operation, "DebugLevel") == 0) {
316                 answer_integer = serverinfo->dwDebugLevel;
317                 is_integer = 1;
318         } else if (strcasecmp(operation, "DefaultAgingState") == 0) {
319                 answer_integer = serverinfo->fDefaultAgingState;
320                 is_integer = 1;
321         } else if (strcasecmp(operation, "DefaultNoRefreshInterval") == 0) {
322                 answer_integer = serverinfo->dwDefaultNoRefreshInterval;
323                 is_integer = 1;
324         } else if (strcasecmp(operation, "DefaultRefreshInterval") == 0) {
325                 answer_integer = serverinfo->dwDefaultRefreshInterval;
326                 is_integer = 1;
327         } else if (strcasecmp(operation, "DeleteOutsideGlue") == 0) {
328                 answer_integer = 0;
329                 is_integer = 1;
330         } else if (strcasecmp(operation, "DisjointNets") == 0) {
331                 answer_integer = 0;
332                 is_integer = 1;
333         } else if (strcasecmp(operation, "DsLazyUpdateInterval") == 0) {
334                 answer_integer = 3; /* seconds */
335                 is_integer = 1;
336         } else if (strcasecmp(operation, "DsPollingInterval") == 0) {
337                 answer_integer = serverinfo->dwDsPollingInterval;
338                 is_integer = 1;
339         } else if (strcasecmp(operation, "DsTombstoneInterval") == 0) {
340                 answer_integer = 0x00127500; /* 14 days */
341                 is_integer = 1;
342         } else if (strcasecmp(operation, "EnableRegistryBoot") == 0) {
343                 answer_integer = 0;
344                 is_integer = 1;
345         } else if (strcasecmp(operation, "EventLogLevel") == 0) {
346                 answer_integer = serverinfo->dwEventLogLevel;
347                 is_integer = 1;
348         } else if (strcasecmp(operation, "ForceSoaSerial") == 0) {
349                 answer_integer = 0;
350                 is_integer = 1;
351         } else if (strcasecmp(operation, "ForceSaoRetry") == 0) {
352                 answer_integer = 0;
353                 is_integer = 1;
354         } else if (strcasecmp(operation, "ForceSoaRefresh") == 0) {
355                 answer_integer = 0;
356                 is_integer = 1;
357         } else if (strcasecmp(operation, "ForceSoaMinimumTtl") == 0) {
358                 answer_integer = 0;
359                 is_integer = 1;
360         } else if (strcasecmp(operation, "ForwardDelegations") == 0) {
361                 answer_integer = 1;
362                 is_integer = 1;
363         } else if (strcasecmp(operation, "ForwardingTimeout") == 0) {
364                 answer_integer = serverinfo->dwForwardTimeout;
365                 is_integer = 1;
366         } else if (strcasecmp(operation, "IsSlave") == 0) {
367                 answer_integer = 0;
368                 is_integer = 1;
369         } else if (strcasecmp(operation, "LocalNetPriority") == 0) {
370                 answer_integer = serverinfo->fLocalNetPriority;
371                 is_integer = 1;
372         } else if (strcasecmp(operation, "LogFileMaxSize") == 0) {
373                 answer_integer = serverinfo->dwLogFileMaxSize;
374                 is_integer = 1;
375         } else if (strcasecmp(operation, "LogLevel") == 0) {
376                 answer_integer = serverinfo->dwLogLevel;
377                 is_integer = 1;
378         } else if (strcasecmp(operation, "LooseWildcarding") == 0) {
379                 answer_integer = serverinfo->fLooseWildcarding;
380                 is_integer = 1;
381         } else if (strcasecmp(operation, "MaxCacheTtl") == 0) {
382                 answer_integer = serverinfo->dwMaxCacheTtl;
383                 is_integer = 1;
384         } else if (strcasecmp(operation, "MaxNegativeCacheTtl") == 0) {
385                 answer_integer = 0x00000384; /* 15 minutes */
386                 is_integer = 1;
387         } else if (strcasecmp(operation, "NameCheckFlag") == 0) {
388                 answer_integer = serverinfo->dwNameCheckFlag;
389                 is_integer = 1;
390         } else if (strcasecmp(operation, "NoRecursion") == 0) {
391                 answer_integer = serverinfo->fNoRecursion;
392                 is_integer = 1;
393         } else if (strcasecmp(operation, "NoUpdateDelegations") == 0) {
394                 answer_integer = 1;
395                 is_integer = 1;
396         } else if (strcasecmp(operation, "PublishAutonet") == 0) {
397                 answer_integer = 0;
398                 is_integer = 1;
399         } else if (strcasecmp(operation, "QuietRecvFaultInterval") == 0) {
400                 answer_integer = 0;
401                 is_integer = 1;
402         } else if (strcasecmp(operation, "QuietRecvLogInterval") == 0) {
403                 answer_integer = 0;
404                 is_integer = 1;
405         } else if (strcasecmp(operation, "RecursionRetry") == 0) {
406                 answer_integer = serverinfo->dwRecursionRetry;
407                 is_integer = 1;
408         } else if (strcasecmp(operation, "RecursionTimeout") == 0) {
409                 answer_integer = serverinfo->dwRecursionTimeout;
410                 is_integer = 1;
411         } else if (strcasecmp(operation, "ReloadException") == 0) {
412                 answer_integer = 0;
413                 is_integer = 1;
414         } else if (strcasecmp(operation, "RoundRobin") == 0) {
415                 answer_integer = serverinfo->fRoundRobin;
416                 is_integer = 1;
417         } else if (strcasecmp(operation, "RpcProtocol") == 0) {
418                 answer_integer = serverinfo->dwRpcProtocol;
419                 is_integer = 1;
420         } else if (strcasecmp(operation, "SecureResponses") == 0) {
421                 answer_integer = serverinfo->fSecureResponses;
422                 is_integer = 1;
423         } else if (strcasecmp(operation, "SendPort") == 0) {
424                 answer_integer = 0;
425                 is_integer = 1;
426         } else if (strcasecmp(operation, "ScavengingInterval") == 0) {
427                 answer_integer = serverinfo->dwScavengingInterval;
428                 is_integer = 1;
429         } else if (strcasecmp(operation, "SocketPoolSize") == 0) {
430                 answer_integer = 0x000009C4;
431                 is_integer = 1;
432         } else if (strcasecmp(operation, "StrictFileParsing") == 0) {
433                 answer_integer = serverinfo->fStrictFileParsing;
434                 is_integer = 1;
435         } else if (strcasecmp(operation, "SyncDnsZoneSerial") == 0) {
436                 answer_integer = 2; /* ZONE_SERIAL_SYNC_XFER */
437                 is_integer = 1;
438         } else if (strcasecmp(operation, "UpdateOptions") == 0) {
439                 answer_integer = 0x0000030F; /* DNS_DEFAULT_UPDATE_OPTIONS */
440                 is_integer = 1;
441         } else if (strcasecmp(operation, "UseSystemEvengLog") == 0) {
442                 answer_integer = 0;
443                 is_integer = 1;
444         } else if (strcasecmp(operation, "Version") == 0) {
445                 answer_integer = serverinfo->dwVersion;
446                 is_integer = 1;
447         } else if (strcasecmp(operation, "XfrConnectTimeout") == 0) {
448                 answer_integer = 0x0000001E;
449                 is_integer = 1;
450         } else if (strcasecmp(operation, "WriteAuthorityNs") == 0) {
451                 answer_integer = serverinfo->fWriteAuthorityNs;
452                 is_integer = 1;
453         } else if (strcasecmp(operation, "AdditionalRecursionTimeout") == 0) {
454                 answer_integer = 0x00000004;
455                 is_integer = 1;
456         } else if (strcasecmp(operation, "AppendMsZoneTransferFlag") == 0) {
457                 answer_integer = 0;
458                 is_integer = 1;
459         } else if (strcasecmp(operation, "AutoCreateDelegations") == 0) {
460                 answer_integer = 0; /* DNS_ACD_DONT_CREATE */
461                 is_integer = 1;
462         } else if (strcasecmp(operation, "BreakOnAscFailure") == 0) {
463                 answer_integer = 0;
464                 is_integer = 1;
465         } else if (strcasecmp(operation, "CacheEmptyAuthResponses") == 0) {
466                 answer_integer = 0;
467                 is_integer = 1;
468         } else if (strcasecmp(operation, "DirectoryPartitionAutoEnlistInterval") == 0) {
469                 answer_integer = 0x00015180; /* 1 day */
470                 is_integer = 1;
471         } else if (strcasecmp(operation, "DisableAutoReverseZones") == 0) {
472                 answer_integer = ~serverinfo->fAutoReverseZones;
473                 is_integer = 1;
474         } else if (strcasecmp(operation, "EDnsCacheTimeout") == 0) {
475                 answer_integer = 0x00000384; /* 15 minutes */
476                 is_integer = 1;
477         } else if (strcasecmp(operation, "EnableDirectoryPartitions") == 0) {
478                 answer_integer = serverinfo->fDsAvailable;
479                 is_integer = 1;
480         } else if (strcasecmp(operation, "EnableDnsSec") == 0) {
481                 answer_integer = 0;
482                 is_integer = 1;
483         } else if (strcasecmp(operation, "EnableEDnsProbes") == 0) {
484                 answer_integer = 0;
485                 is_integer = 1;
486         } else if (strcasecmp(operation, "EnableEDnsReception") == 0) {
487                 answer_integer = 0;
488                 is_integer = 1;
489         } else if (strcasecmp(operation, "EnableIPv6") == 0) {
490                 answer_integer = 0;
491                 is_integer = 1;
492         } else if (strcasecmp(operation, "EnableIQueryResponseGeneration") == 0) {
493                 answer_integer = 0;
494                 is_integer = 1;
495         } else if (strcasecmp(operation, "EnableSendErrorSuppression") == 0) {
496                 answer_integer = 0;
497                 is_integer = 1;
498         } else if (strcasecmp(operation, "EnableUpdateForwarding") == 0) {
499                 answer_integer = 0;
500                 is_integer = 1;
501         } else if (strcasecmp(operation, "EnableWinsR") == 0) {
502                 answer_integer = 0;
503                 is_integer = 1;
504         } else if (strcasecmp(operation, "ForceDsaBehaviorVersion") == 0) {
505                 answer_integer = serverinfo->dwDsDsaVersion;
506                 is_integer = 1;
507         } else if (strcasecmp(operation, "ForceDomainBehaviorVersion") == 0) {
508                 answer_integer = serverinfo->dwDsDsaVersion;
509                 is_integer = 1;
510         } else if (strcasecmp(operation, "ForceForestBehaviorVersion") == 0) {
511                 answer_integer = serverinfo->dwDsDsaVersion;
512                 is_integer = 1;
513         } else if (strcasecmp(operation, "HeapDebug") == 0) {
514                 answer_integer = 0;
515                 is_integer = 1;
516         } else if (strcasecmp(operation, "LameDelegationTtl") == 0) {
517                 answer_integer = 0; /* seconds */
518                 is_integer = 1;
519         } else if (strcasecmp(operation, "LocalNetPriorityNetMask") == 0) {
520                 answer_integer = serverinfo->dwLocalNetPriorityNetMask;
521                 is_integer = 1;
522         } else if (strcasecmp(operation, "MaxCacheSize") == 0) {
523                 answer_integer = 0;
524                 is_integer = 1;
525         } else if (strcasecmp(operation, "MaxResourceRecordsInNonSecureUpdate") == 0) {
526                 answer_integer = 0x0000001E;
527                 is_integer = 1;
528         } else if (strcasecmp(operation, "OperationsLogLevel") == 0) {
529                 answer_integer = 0;
530                 is_integer = 1;
531         } else if (strcasecmp(operation, "OperationsLogLevel2") == 0) {
532                 answer_integer = 0;
533                 is_integer = 1;
534         } else if (strcasecmp(operation, "MaximumUdpPacketSize") == 0) {
535                 answer_integer = 0x00004000; /* maximum possible */
536                 is_integer = 1;
537         } else if (strcasecmp(operation, "RecurseToInternetRootMask") == 0) {
538                 answer_integer = 0;
539                 is_integer = 1;
540         } else if (strcasecmp(operation, "SelfTest") == 0) {
541                 answer_integer = 0;
542                 is_integer = 1;
543         } else if (strcasecmp(operation, "SilentlyIgnoreCNameUpdateConflicts") == 0) {
544                 answer_integer = 1;
545                 is_integer = 1;
546         } else if (strcasecmp(operation, "TcpReceivePacketSize") == 0) {
547                 answer_integer = 0x00010000;
548                 is_integer = 1;
549         } else if (strcasecmp(operation, "XfrThrottleMultiplier") == 0) {
550                 answer_integer = 0x0000000A;
551                 is_integer = 1;
552         } else if (strcasecmp(operation, "AllowMsdcsLookupRetry") == 0) {
553                 answer_integer = 1;
554                 is_integer = 1;
555         } else if (strcasecmp(operation, "AllowReadOnlyZoneTransfer") == 0) {
556                 answer_integer = 0;
557                 is_integer = 1;
558         } else if (strcasecmp(operation, "DsBackGroundLoadPaused") == 0) {
559                 answer_integer = 0;
560                 is_integer = 1;
561         } else if (strcasecmp(operation, "DsMinimumBackgroundLoadThreads") == 0) {
562                 answer_integer = 0;
563                 is_integer = 1;
564         } else if (strcasecmp(operation, "DsRemoteReplicationDelay") == 0) {
565                 answer_integer = 0x0000001E; /* 30 seconds */
566                 is_integer = 1;
567         } else if (strcasecmp(operation, "EnableDuplicateQuerySuppresion") == 0) {
568                 answer_integer = 0;
569                 is_integer = 1;
570         } else if (strcasecmp(operation, "EnableGlobalNamesSupport") == 0) {
571                 answer_integer = 0;
572                 is_integer = 1;
573         } else if (strcasecmp(operation, "EnableVersionQuery") == 0) {
574                 answer_integer = 1; /* DNS_VERSION_QUERY_FULL */
575                 is_integer = 1;
576         } else if (strcasecmp(operation, "EnableRsoForRodc") == 0) {
577                 answer_integer = 0;
578                 is_integer = 1;
579         } else if (strcasecmp(operation, "ForceRODCMode") == 0) {
580                 answer_integer = 0;
581                 is_integer = 1;
582         } else if (strcasecmp(operation, "GlobalNamesAlwaysQuerySrv") == 0) {
583                 answer_integer = 1;
584                 is_integer = 1;
585         } else if (strcasecmp(operation, "GlobalNamesBlockUpdates") == 0) {
586                 answer_integer = 0;
587                 is_integer = 1;
588         } else if (strcasecmp(operation, "GlobalNamesEnableEDnsProbes") == 0) {
589                 answer_integer = 0;
590                 is_integer = 1;
591         } else if (strcasecmp(operation, "GlobalNamesPreferAAAA") == 0) {
592                 answer_integer = 0;
593                 is_integer = 1;
594         } else if (strcasecmp(operation, "GlobalNamesQueryOrder") == 0) {
595                 answer_integer = 1;
596                 is_integer = 1;
597         } else if (strcasecmp(operation, "GlobalNamesSendTimeout") == 0) {
598                 answer_integer = 3; /* seconds */
599                 is_integer = 1;
600         } else if (strcasecmp(operation, "GlobalNamesServerQueryInterval") == 0) {
601                 answer_integer = 0x00005460; /* 6 hours */
602                 is_integer = 1;
603         } else if (strcasecmp(operation, "RemoteIPv4RankBoost") == 0) {
604                 answer_integer = 0;
605                 is_integer = 1;
606         } else if (strcasecmp(operation, "RemoteIPv6RankBoost") == 0) {
607                 answer_integer = 0;
608                 is_integer = 1;
609         } else if (strcasecmp(operation, "MaximumRodcRsoAttemptsPerCycle") == 0) {
610                 answer_integer = 0x00000064;
611                 is_integer = 1;
612         } else if (strcasecmp(operation, "MaximumRodcRsoQueueLength") == 0) {
613                 answer_integer = 0x0000012C;
614                 is_integer = 1;
615         } else if (strcasecmp(operation, "EnableGlobalQueryBlockList") == 0) {
616                 answer_integer = 0;
617                 is_integer = 1;
618         } else if (strcasecmp(operation, "OpenACLOnProxyUpdates") == 0) {
619                 answer_integer = 0;
620                 is_integer = 1;
621         } else if (strcasecmp(operation, "CacheLockingPercent") == 0) {
622                 answer_integer = 0x00000064;
623                 is_integer = 1;
624         }
625
626         if (is_integer == 1) {
627                 *typeid = DNSSRV_TYPEID_DWORD;
628                 r->Dword = answer_integer;
629                 return WERR_OK;
630         }
631
632         is_addresses = 0;
633
634         if (strcasecmp(operation, "Forwarders") == 0) {
635                 if (client_version == DNS_CLIENT_VERSION_LONGHORN) {
636                         answer_addrarray = ip4_array_to_dns_addr_array(mem_ctx, serverinfo->aipForwarders);
637                 } else {
638                         answer_iparray = ip4_array_copy(mem_ctx, serverinfo->aipForwarders);
639                 }
640                 is_addresses = 1;
641         } else if (strcasecmp(operation, "ListenAddresses") == 0) {
642                 if (client_version == DNS_CLIENT_VERSION_LONGHORN) {
643                         answer_addrarray = ip4_array_to_dns_addr_array(mem_ctx, serverinfo->aipListenAddrs);
644                 } else {
645                         answer_iparray = ip4_array_copy(mem_ctx, serverinfo->aipListenAddrs);
646                 }
647                 is_addresses = 1;
648         } else if (strcasecmp(operation, "BreakOnReceiveFrom") == 0) {
649                 if (client_version == DNS_CLIENT_VERSION_LONGHORN) {
650                         answer_addrarray = NULL;
651                 } else {
652                         answer_iparray = NULL;
653                 }
654                 is_addresses = 1;
655         } else if (strcasecmp(operation, "BreakOnUpdateFrom") == 0) {
656                 if (client_version == DNS_CLIENT_VERSION_LONGHORN) {
657                         answer_addrarray = NULL;
658                 } else {
659                         answer_iparray = NULL;
660                 }
661                 is_addresses = 1;
662         } else if (strcasecmp(operation, "LogIPFilterList") == 0) {
663                 if (client_version == DNS_CLIENT_VERSION_LONGHORN) {
664                         answer_addrarray = ip4_array_to_dns_addr_array(mem_ctx, serverinfo->aipLogFilter);
665                 } else {
666                         answer_iparray = ip4_array_copy(mem_ctx, serverinfo->aipLogFilter);
667                 }
668                 is_addresses = 1;
669         }
670
671         if (is_addresses == 1) {
672                 if (client_version == DNS_CLIENT_VERSION_LONGHORN) {
673                         *typeid = DNSSRV_TYPEID_ADDRARRAY;
674                         r->AddrArray = answer_addrarray;
675                 } else {
676                         *typeid = DNSSRV_TYPEID_IPARRAY;
677                         r->IpArray = answer_iparray;
678                 }
679                 return WERR_OK;
680         }
681
682         is_string = is_wstring = 0;
683
684         if (strcasecmp(operation, "DomainDirectoryPartitionBaseName") == 0) {
685                 answer_string = talloc_strdup(mem_ctx, "DomainDnsZones");
686                 if (! answer_string) {
687                         return WERR_OUTOFMEMORY;
688                 }
689                 is_string = 1;
690         } else if (strcasecmp(operation, "ForestDirectoryPartitionBaseName") == 0) {
691                 answer_string = talloc_strdup(mem_ctx, "ForestDnsZones");
692                 if (! answer_string) {
693                         return WERR_OUTOFMEMORY;
694                 }
695                 is_string = 1;
696         } else if (strcasecmp(operation, "LogFilePath") == 0) {
697                 answer_string = talloc_strdup(mem_ctx, serverinfo->pwszLogFilePath);
698                 is_wstring = 1;
699         } else if (strcasecmp(operation, "ServerLevelPluginDll") == 0) {
700                 answer_string = NULL;
701                 is_wstring = 1;
702         } else if (strcasecmp(operation, "DsBackgroundPauseName") == 0) {
703                 answer_string = NULL;
704                 is_string = 1;
705         } else if (strcasecmp(operation, "DsNotRoundRobinTypes") == 0) {
706                 answer_string = NULL;
707                 is_string = 1;
708         }
709
710         if (is_string == 1) {
711                 *typeid = DNSSRV_TYPEID_LPSTR;
712                 r->String = answer_string;
713                 return WERR_OK;
714         } else if (is_wstring == 1) {
715                 *typeid = DNSSRV_TYPEID_LPWSTR;
716                 r->WideString = answer_string;
717                 return WERR_OK;
718         }
719
720         is_stringlist = 0;
721
722         if (strcasecmp(operation, "GlobalQueryBlockList") == 0) {
723                 answer_stringlist = NULL;
724                 is_stringlist = 1;
725         } else if (strcasecmp(operation, "SocketPoolExcludedPortRanges") == 0) {
726                 answer_stringlist = NULL;
727                 is_stringlist = 1;
728         }
729
730         if (is_stringlist == 1) {
731                 *typeid = DNSSRV_TYPEID_UTF8_STRING_LIST;
732                 r->Utf8StringList = answer_stringlist;
733                 return WERR_OK;
734         }
735
736         DEBUG(0,("dnsserver: Invalid server operation %s", operation));
737         return WERR_DNS_ERROR_INVALID_PROPERTY;
738 }
739
740 /* [MS-DNSP].pdf Section 3.1.1.2 Zone Configuration Information */
741 static WERROR dnsserver_query_zone(struct dnsserver_state *dsstate,
742                                         TALLOC_CTX *mem_ctx,
743                                         struct dnsserver_zone *z,
744                                         const char *operation,
745                                         const unsigned int client_version,
746                                         enum DNS_RPC_TYPEID *typeid,
747                                         union DNSSRV_RPC_UNION *r)
748 {
749         uint8_t is_integer, is_addresses, is_string;
750         uint32_t answer_integer;
751         struct IP4_ARRAY *answer_iparray;
752         struct DNS_ADDR_ARRAY *answer_addrarray;
753         char *answer_string;
754         struct dnsserver_zoneinfo *zoneinfo;
755
756         zoneinfo = z->zoneinfo;
757
758         if (strcasecmp(operation, "Zone") == 0) {
759                 if (client_version == DNS_CLIENT_VERSION_W2K) {
760                         *typeid = DNSSRV_TYPEID_ZONE_W2K;
761                         r->ZoneW2K = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_W2K);
762
763                         r->ZoneW2K->pszZoneName = talloc_strdup(mem_ctx, z->name);
764                         r->ZoneW2K->Flags = zoneinfo->Flags;
765                         r->ZoneW2K->ZoneType = zoneinfo->dwZoneType;
766                         r->ZoneW2K->Version = zoneinfo->Version;
767                 } else {
768                         *typeid = DNSSRV_TYPEID_ZONE;
769                         r->Zone = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_DOTNET);
770
771                         r->Zone->dwRpcStructureVersion = 0x01;
772                         r->Zone->pszZoneName = talloc_strdup(mem_ctx, z->name);
773                         r->Zone->Flags = zoneinfo->Flags;
774                         r->Zone->ZoneType = zoneinfo->dwZoneType;
775                         r->Zone->Version = zoneinfo->Version;
776                         r->Zone->dwDpFlags = zoneinfo->dwDpFlags;
777                         r->Zone->pszDpFqdn = talloc_strdup(mem_ctx, zoneinfo->pszDpFqdn);
778                 }
779                 return WERR_OK;
780         }
781
782         if (strcasecmp(operation, "ZoneInfo") == 0) {
783                 if (client_version == DNS_CLIENT_VERSION_W2K) {
784                         *typeid = DNSSRV_TYPEID_ZONE_INFO_W2K;
785                         r->ZoneInfoW2K = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_INFO_W2K);
786
787                         r->ZoneInfoW2K->pszZoneName = talloc_strdup(mem_ctx, z->name);
788                         r->ZoneInfoW2K->dwZoneType = zoneinfo->dwZoneType;
789                         r->ZoneInfoW2K->fReverse = zoneinfo->fReverse;
790                         r->ZoneInfoW2K->fAllowUpdate = zoneinfo->fAllowUpdate;
791                         r->ZoneInfoW2K->fPaused = zoneinfo->fPaused;
792                         r->ZoneInfoW2K->fShutdown = zoneinfo->fShutdown;
793                         r->ZoneInfoW2K->fAutoCreated = zoneinfo->fAutoCreated;
794                         r->ZoneInfoW2K->fUseDatabase = zoneinfo->fUseDatabase;
795                         r->ZoneInfoW2K->pszDataFile = talloc_strdup(mem_ctx, zoneinfo->pszDataFile);
796                         r->ZoneInfoW2K->aipMasters = ip4_array_copy(mem_ctx, zoneinfo->aipMasters);
797                         r->ZoneInfoW2K->fSecureSecondaries = zoneinfo->fSecureSecondaries;
798                         r->ZoneInfoW2K->fNotifyLevel = zoneinfo->fNotifyLevel;
799                         r->ZoneInfoW2K->aipSecondaries = ip4_array_copy(mem_ctx, zoneinfo->aipSecondaries);
800                         r->ZoneInfoW2K->aipNotify = ip4_array_copy(mem_ctx, zoneinfo->aipNotify);
801                         r->ZoneInfoW2K->fUseWins = zoneinfo->fUseWins;
802                         r->ZoneInfoW2K->fUseNbstat = zoneinfo->fUseNbstat;
803                         r->ZoneInfoW2K->fAging = zoneinfo->fAging;
804                         r->ZoneInfoW2K->dwNoRefreshInterval = zoneinfo->dwNoRefreshInterval;
805                         r->ZoneInfoW2K->dwRefreshInterval = zoneinfo->dwRefreshInterval;
806                         r->ZoneInfoW2K->dwAvailForScavengeTime = zoneinfo->dwAvailForScavengeTime;
807                         r->ZoneInfoW2K->aipScavengeServers = ip4_array_copy(mem_ctx, zoneinfo->aipScavengeServers);
808
809                 } else if (client_version == DNS_CLIENT_VERSION_DOTNET) {
810                         *typeid = DNSSRV_TYPEID_ZONE_INFO_DOTNET;
811                         r->ZoneInfoDotNet = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_INFO_DOTNET);
812
813                         r->ZoneInfoDotNet->dwRpcStructureVersion = 0x01;
814                         r->ZoneInfoDotNet->pszZoneName = talloc_strdup(mem_ctx, z->name);
815                         r->ZoneInfoDotNet->dwZoneType = zoneinfo->dwZoneType;
816                         r->ZoneInfoDotNet->fReverse = zoneinfo->fReverse;
817                         r->ZoneInfoDotNet->fAllowUpdate = zoneinfo->fAllowUpdate;
818                         r->ZoneInfoDotNet->fPaused = zoneinfo->fPaused;
819                         r->ZoneInfoDotNet->fShutdown = zoneinfo->fShutdown;
820                         r->ZoneInfoDotNet->fAutoCreated = zoneinfo->fAutoCreated;
821                         r->ZoneInfoDotNet->fUseDatabase = zoneinfo->fUseDatabase;
822                         r->ZoneInfoDotNet->pszDataFile = talloc_strdup(mem_ctx, zoneinfo->pszDataFile);
823                         r->ZoneInfoDotNet->aipMasters = ip4_array_copy(mem_ctx, zoneinfo->aipMasters);
824                         r->ZoneInfoDotNet->fSecureSecondaries = zoneinfo->fSecureSecondaries;
825                         r->ZoneInfoDotNet->fNotifyLevel = zoneinfo->fNotifyLevel;
826                         r->ZoneInfoDotNet->aipSecondaries = ip4_array_copy(mem_ctx, zoneinfo->aipSecondaries);
827                         r->ZoneInfoDotNet->aipNotify = ip4_array_copy(mem_ctx, zoneinfo->aipNotify);
828                         r->ZoneInfoDotNet->fUseWins = zoneinfo->fUseWins;
829                         r->ZoneInfoDotNet->fUseNbstat = zoneinfo->fUseNbstat;
830                         r->ZoneInfoDotNet->fAging = zoneinfo->fAging;
831                         r->ZoneInfoDotNet->dwNoRefreshInterval = zoneinfo->dwNoRefreshInterval;
832                         r->ZoneInfoDotNet->dwRefreshInterval = zoneinfo->dwRefreshInterval;
833                         r->ZoneInfoDotNet->dwAvailForScavengeTime = zoneinfo->dwAvailForScavengeTime;
834                         r->ZoneInfoDotNet->aipScavengeServers = ip4_array_copy(mem_ctx, zoneinfo->aipScavengeServers);
835                         r->ZoneInfoDotNet->dwForwarderTimeout = zoneinfo->dwForwarderTimeout;
836                         r->ZoneInfoDotNet->fForwarderSlave = zoneinfo->fForwarderSlave;
837                         r->ZoneInfoDotNet->aipLocalMasters = ip4_array_copy(mem_ctx, zoneinfo->aipLocalMasters);
838                         r->ZoneInfoDotNet->dwDpFlags = zoneinfo->dwDpFlags;
839                         r->ZoneInfoDotNet->pszDpFqdn = talloc_strdup(mem_ctx, zoneinfo->pszDpFqdn);
840                         r->ZoneInfoDotNet->pwszZoneDn = talloc_strdup(mem_ctx, zoneinfo->pwszZoneDn);
841                         r->ZoneInfoDotNet->dwLastSuccessfulSoaCheck = zoneinfo->dwLastSuccessfulSoaCheck;
842                         r->ZoneInfoDotNet->dwLastSuccessfulXfr = zoneinfo->dwLastSuccessfulXfr;
843
844                 } else {
845                         *typeid = DNSSRV_TYPEID_ZONE_INFO;
846                         r->ZoneInfo = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_INFO_LONGHORN);
847
848                         r->ZoneInfo->dwRpcStructureVersion = 0x02;
849                         r->ZoneInfo->pszZoneName = talloc_strdup(mem_ctx, z->name);
850                         r->ZoneInfo->dwZoneType = zoneinfo->dwZoneType;
851                         r->ZoneInfo->fReverse = zoneinfo->fReverse;
852                         r->ZoneInfo->fAllowUpdate = zoneinfo->fAllowUpdate;
853                         r->ZoneInfo->fPaused = zoneinfo->fPaused;
854                         r->ZoneInfo->fShutdown = zoneinfo->fShutdown;
855                         r->ZoneInfo->fAutoCreated = zoneinfo->fAutoCreated;
856                         r->ZoneInfo->fUseDatabase = zoneinfo->fUseDatabase;
857                         r->ZoneInfo->pszDataFile = talloc_strdup(mem_ctx, zoneinfo->pszDataFile);
858                         r->ZoneInfo->aipMasters = ip4_array_to_dns_addr_array(mem_ctx, zoneinfo->aipMasters);
859                         r->ZoneInfo->fSecureSecondaries = zoneinfo->fSecureSecondaries;
860                         r->ZoneInfo->fNotifyLevel = zoneinfo->fNotifyLevel;
861                         r->ZoneInfo->aipSecondaries = ip4_array_to_dns_addr_array(mem_ctx, zoneinfo->aipSecondaries);
862                         r->ZoneInfo->aipNotify = ip4_array_to_dns_addr_array(mem_ctx, zoneinfo->aipNotify);
863                         r->ZoneInfo->fUseWins = zoneinfo->fUseWins;
864                         r->ZoneInfo->fUseNbstat = zoneinfo->fUseNbstat;
865                         r->ZoneInfo->fAging = zoneinfo->fAging;
866                         r->ZoneInfo->dwNoRefreshInterval = zoneinfo->dwNoRefreshInterval;
867                         r->ZoneInfo->dwRefreshInterval = zoneinfo->dwRefreshInterval;
868                         r->ZoneInfo->dwAvailForScavengeTime = zoneinfo->dwAvailForScavengeTime;
869                         r->ZoneInfo->aipScavengeServers = ip4_array_to_dns_addr_array(mem_ctx, zoneinfo->aipScavengeServers);
870                         r->ZoneInfo->dwForwarderTimeout = zoneinfo->dwForwarderTimeout;
871                         r->ZoneInfo->fForwarderSlave = zoneinfo->fForwarderSlave;
872                         r->ZoneInfo->aipLocalMasters = ip4_array_to_dns_addr_array(mem_ctx, zoneinfo->aipLocalMasters);
873                         r->ZoneInfo->dwDpFlags = zoneinfo->dwDpFlags;
874                         r->ZoneInfo->pszDpFqdn = talloc_strdup(mem_ctx, zoneinfo->pszDpFqdn);
875                         r->ZoneInfo->pwszZoneDn = talloc_strdup(mem_ctx, zoneinfo->pwszZoneDn);
876                         r->ZoneInfo->dwLastSuccessfulSoaCheck = zoneinfo->dwLastSuccessfulSoaCheck;
877                         r->ZoneInfo->dwLastSuccessfulXfr = zoneinfo->dwLastSuccessfulXfr;
878
879                         r->ZoneInfo->fQueuedForBackgroundLoad = zoneinfo->fQueuedForBackgroundLoad;
880                         r->ZoneInfo->fBackgroundLoadInProgress = zoneinfo->fBackgroundLoadInProgress;
881                         r->ZoneInfo->fReadOnlyZone = zoneinfo->fReadOnlyZone;
882                         r->ZoneInfo->dwLastXfrAttempt = zoneinfo->dwLastXfrAttempt;
883                         r->ZoneInfo->dwLastXfrResult = zoneinfo->dwLastXfrResult;
884                 }
885
886                 return WERR_OK;
887         }
888
889         is_integer = 0;
890
891         if (strcasecmp(operation, "AllowUpdate") == 0) {
892                 answer_integer = zoneinfo->fAllowUpdate;
893                 is_integer = 1;
894         } else if (strcasecmp(operation, "Secured") == 0) {
895                 answer_integer = 0;
896                 is_integer = 1;
897         } else if (strcasecmp(operation, "DsIntegrated") == 0) {
898                 answer_integer = zoneinfo->fUseDatabase;
899                 is_integer = 1;
900         } else if (strcasecmp(operation, "LogUpdates") == 0) {
901                 answer_integer = 0;
902                 is_integer = 1;
903         } else if (strcasecmp(operation, "NoRefreshInterval") == 0) {
904                 answer_integer = zoneinfo->dwNoRefreshInterval;
905                 is_integer = 1;
906         } else if (strcasecmp(operation, "NotifyLevel") == 0) {
907                 answer_integer = zoneinfo->fNotifyLevel;
908                 is_integer = 1;
909         } else if (strcasecmp(operation, "RefreshInterval") == 0) {
910                 answer_integer = zoneinfo->dwRefreshInterval;
911                 is_integer = 1;
912         } else if (strcasecmp(operation, "SecureSecondaries") == 0) {
913                 answer_integer = zoneinfo->fSecureSecondaries;
914                 is_integer = 1;
915         } else if (strcasecmp(operation, "Type") == 0) {
916                 answer_integer = zoneinfo->dwZoneType;
917                 is_integer = 1;
918         } else if (strcasecmp(operation, "Aging") == 0) {
919                 answer_integer = zoneinfo->fAging;
920                 is_integer = 1;
921         } else if (strcasecmp(operation, "ForwarderSlave") == 0) {
922                 answer_integer = zoneinfo->fForwarderSlave;
923                 is_integer = 1;
924         } else if (strcasecmp(operation, "ForwarderTimeout") == 0) {
925                 answer_integer = zoneinfo->dwForwarderTimeout;
926                 is_integer = 1;
927         } else if (strcasecmp(operation, "Unicode") == 0) {
928                 answer_integer = 0;
929                 is_integer = 1;
930         }
931
932         if (is_integer == 1) {
933                 *typeid = DNSSRV_TYPEID_DWORD;
934                 r->Dword = answer_integer;
935                 return WERR_OK;
936         }
937
938         is_addresses = 0;
939
940         if (strcasecmp(operation, "AllowNSRecordsAutoCreation") == 0) {
941                 if (client_version == DNS_CLIENT_VERSION_LONGHORN) {
942                         answer_addrarray = NULL;
943                 } else {
944                         answer_iparray = NULL;
945                 }
946                 is_addresses = 1;
947         } else if (strcasecmp(operation, "ScavengeServers") == 0) {
948                 if (client_version == DNS_CLIENT_VERSION_LONGHORN) {
949                         answer_addrarray = ip4_array_to_dns_addr_array(mem_ctx, zoneinfo->aipScavengeServers);
950                 } else {
951                         answer_iparray = ip4_array_copy(mem_ctx, zoneinfo->aipScavengeServers);
952                 }
953                 is_addresses = 1;
954         } else if (strcasecmp(operation, "MasterServers") == 0) {
955                 if (client_version == DNS_CLIENT_VERSION_LONGHORN) {
956                         answer_addrarray = ip4_array_to_dns_addr_array(mem_ctx, zoneinfo->aipMasters);
957                 } else {
958                         answer_iparray = ip4_array_copy(mem_ctx, zoneinfo->aipMasters);
959                 }
960                 is_addresses = 1;
961         } else if (strcasecmp(operation, "LocalMasterServers") == 0) {
962                 if (client_version == DNS_CLIENT_VERSION_LONGHORN) {
963                         answer_addrarray = ip4_array_to_dns_addr_array(mem_ctx, zoneinfo->aipLocalMasters);
964                 } else {
965                         answer_iparray = ip4_array_copy(mem_ctx, zoneinfo->aipLocalMasters);
966                 }
967                 is_addresses = 1;
968         } else if (strcasecmp(operation, "NotifyServers") == 0) {
969                 if (client_version == DNS_CLIENT_VERSION_LONGHORN) {
970                         answer_addrarray = ip4_array_to_dns_addr_array(mem_ctx, zoneinfo->aipNotify);
971                 } else {
972                         answer_iparray = ip4_array_copy(mem_ctx, zoneinfo->aipNotify);
973                 }
974                 is_addresses = 1;
975         } else if (strcasecmp(operation, "SecondaryServers") == 0) {
976                 if (client_version == DNS_CLIENT_VERSION_LONGHORN) {
977                         answer_addrarray = ip4_array_to_dns_addr_array(mem_ctx, zoneinfo->aipSecondaries);
978                 } else {
979                         answer_iparray = ip4_array_copy(mem_ctx, zoneinfo->aipSecondaries);
980                 }
981                 is_addresses = 1;
982         }
983
984         if (is_addresses == 1) {
985                 if (client_version == DNS_CLIENT_VERSION_LONGHORN) {
986                         *typeid = DNSSRV_TYPEID_ADDRARRAY;
987                         r->AddrArray = answer_addrarray;
988                 } else {
989                         *typeid = DNSSRV_TYPEID_IPARRAY;
990                         r->IpArray = answer_iparray;
991                 }
992                 return WERR_OK;
993         }
994
995         is_string = 0;
996
997         if (strcasecmp(operation, "DatabaseFile") == 0) {
998                 answer_string = talloc_strdup(mem_ctx, zoneinfo->pszDataFile);
999                 is_string = 1;
1000         } else if (strcasecmp(operation, "ApplicationDirectoryPartition") == 0) {
1001                 answer_string = talloc_strdup(mem_ctx, zoneinfo->pszDpFqdn);
1002                 is_string = 1;
1003         } else if (strcasecmp(operation, "BreakOnNameUpdate") == 0) {
1004                 answer_string = NULL;
1005                 is_string = 1;
1006         }
1007
1008         if (is_string == 1) {
1009                 *typeid = DNSSRV_TYPEID_LPSTR;
1010                 r->String = answer_string;
1011                 return WERR_OK;
1012         }
1013
1014         DEBUG(0,("dnsserver: Invalid zone operation %s", operation));
1015         return WERR_DNS_ERROR_INVALID_PROPERTY;
1016
1017 }
1018
1019 /* dnsserver operation functions */
1020
1021 /* [MS-DNSP].pdf Section 3.1.1.1 DNS Server Configuration Information */
1022 static WERROR dnsserver_operate_server(struct dnsserver_state *dsstate,
1023                                         TALLOC_CTX *mem_ctx,
1024                                         const char *operation,
1025                                         const unsigned int client_version,
1026                                         enum DNS_RPC_TYPEID typeid,
1027                                         union DNSSRV_RPC_UNION *r)
1028 {
1029         bool valid_operation = false;
1030
1031         if (strcasecmp(operation, "ResetDwordProperty") == 0) {
1032                 valid_operation = true;
1033         } else if (strcasecmp(operation, "Restart") == 0) {
1034                 valid_operation = true;
1035         } else if (strcasecmp(operation, "ClearDebugLog") == 0) {
1036                 valid_operation = true;
1037         } else if (strcasecmp(operation, "ClearCache") == 0) {
1038                 valid_operation = true;
1039         } else if (strcasecmp(operation, "WriteDirtyZones") == 0) {
1040                 valid_operation = true;
1041         } else if (strcasecmp(operation, "ZoneCreate") == 0) {
1042                 valid_operation = true;
1043         } else if (strcasecmp(operation, "ClearStatistics") == 0) {
1044                 valid_operation = true;
1045         } else if (strcasecmp(operation, "EnlistDirectoryPartition") == 0) {
1046                 valid_operation = true;
1047         } else if (strcasecmp(operation, "StartScavenging") == 0) {
1048                 valid_operation = true;
1049         } else if (strcasecmp(operation, "AbortScavenging") == 0) {
1050                 valid_operation = true;
1051         } else if (strcasecmp(operation, "AutoConfigure") == 0) {
1052                 valid_operation = true;
1053         } else if (strcasecmp(operation, "ExportSettings") == 0) {
1054                 valid_operation = true;
1055         } else if (strcasecmp(operation, "PrepareForDemotion") == 0) {
1056                 valid_operation = true;
1057         } else if (strcasecmp(operation, "PrepareForUninstall") == 0) {
1058                 valid_operation = true;
1059         } else if (strcasecmp(operation, "DeleteNode") == 0) {
1060                 valid_operation = true;
1061         } else if (strcasecmp(operation, "DeleteRecord") == 0) {
1062                 valid_operation = true;
1063         } else if (strcasecmp(operation, "WriteBackFile") == 0) {
1064                 valid_operation = true;
1065         } else if (strcasecmp(operation, "ListenAddresses") == 0) {
1066                 valid_operation = true;
1067         } else if (strcasecmp(operation, "Forwarders") == 0) {
1068                 valid_operation = true;
1069         } else if (strcasecmp(operation, "LogFilePath") == 0) {
1070                 valid_operation = true;
1071         } else if (strcasecmp(operation, "LogIpFilterList") == 0) {
1072                 valid_operation = true;
1073         } else if (strcasecmp(operation, "ForestDirectoryPartitionBaseName") == 0) {
1074                 valid_operation = true;
1075         } else if (strcasecmp(operation, "DomainDirectoryPartitionBaseName") == 0) {
1076                 valid_operation = true;
1077         } else if (strcasecmp(operation, "GlobalQueryBlockList") == 0) {
1078                 valid_operation = true;
1079         } else if (strcasecmp(operation, "BreakOnReceiveFrom") == 0) {
1080                 valid_operation = true;
1081         } else if (strcasecmp(operation, "BreakOnUpdateFrom") == 0) {
1082                 valid_operation = true;
1083         } else if (strcasecmp(operation, "ServerLevelPluginDll") == 0) {
1084                 valid_operation = true;
1085         }
1086
1087         if (valid_operation) {
1088                 DEBUG(0, ("dnsserver: server operation '%s' not implemented", operation));
1089                 return WERR_CALL_NOT_IMPLEMENTED;
1090         }
1091
1092         DEBUG(0, ("dnsserver: invalid server operation '%s'", operation));
1093         return WERR_DNS_ERROR_INVALID_PROPERTY;
1094 }
1095
1096 static WERROR dnsserver_complex_operate_server(struct dnsserver_state *dsstate,
1097                                         TALLOC_CTX *mem_ctx,
1098                                         const char *operation,
1099                                         const unsigned int client_version,
1100                                         enum DNS_RPC_TYPEID typeid_in,
1101                                         union DNSSRV_RPC_UNION *rin,
1102                                         enum DNS_RPC_TYPEID *typeid_out,
1103                                         union DNSSRV_RPC_UNION *rout)
1104 {
1105         int valid_operation = 0;
1106         struct dnsserver_zone *z, **zlist;
1107         int zcount;
1108         bool found1, found2, found3, found4;
1109         int i;
1110
1111         if (strcasecmp(operation, "QueryDwordProperty") == 0) {
1112                 if (typeid_in == DNSSRV_TYPEID_LPSTR) {
1113                         return dnsserver_query_server(dsstate, mem_ctx,
1114                                                         rin->String,
1115                                                         client_version,
1116                                                         typeid_out,
1117                                                         rout);
1118                 }
1119         } else if (strcasecmp(operation, "EnumZones") == 0) {
1120                 if (typeid_in != DNSSRV_TYPEID_DWORD) {
1121                         return WERR_DNS_ERROR_INVALID_PROPERTY;
1122                 }
1123
1124                 zcount = 0;
1125                 zlist = talloc_zero_array(mem_ctx, struct dnsserver_zone *, 0);
1126                 for (z = dsstate->zones; z; z = z->next) {
1127
1128                         /* Match the flags in groups
1129                          *
1130                          * Group1 : PRIMARY, SECONDARY, CACHE, AUTO
1131                          * Group2 : FORWARD, REVERSE, FORWARDER, STUB
1132                          * Group3 : DS, NON_DS, DOMAIN_DP, FOREST_DP
1133                          * Group4 : CUSTOM_DP, LEGACY_DP
1134                          */
1135                         
1136                         /* Group 1 */
1137                         found1 = false;
1138                         if (rin->Dword & 0x0000000f) {
1139                                 if (rin->Dword & DNS_ZONE_REQUEST_PRIMARY) {
1140                                         if (z->zoneinfo->dwZoneType == DNS_ZONE_TYPE_PRIMARY) {
1141                                         found1 = true;
1142                                         }
1143                                 }
1144                                 if (rin->Dword & DNS_ZONE_REQUEST_SECONDARY) {
1145                                         if (z->zoneinfo->dwZoneType == DNS_ZONE_TYPE_SECONDARY) {
1146                                                 found1 = true;
1147                                         }
1148                                 }
1149                                 if (rin->Dword & DNS_ZONE_REQUEST_CACHE) {
1150                                         if (z->zoneinfo->dwZoneType == DNS_ZONE_TYPE_CACHE) {
1151                                                 found1 = true;
1152                                         }
1153                                 }
1154                                 if (rin->Dword & DNS_ZONE_REQUEST_AUTO) {
1155                                         if (z->zoneinfo->fAutoCreated 
1156                                                 || z->zoneinfo->dwDpFlags & DNS_DP_AUTOCREATED) {
1157                                                 found1 = true;
1158                                         }
1159                                 }
1160                         } else {
1161                                 found1 = true;
1162                         }
1163
1164                         /* Group 2 */
1165                         found2 = false;
1166                         if (rin->Dword & 0x000000f0) {
1167                                 if (rin->Dword & DNS_ZONE_REQUEST_FORWARD) {
1168                                         if (!(z->zoneinfo->fReverse)) {
1169                                                 found2 = true;
1170                                         }
1171                                 }
1172                                 if (rin->Dword & DNS_ZONE_REQUEST_REVERSE) {
1173                                         if (z->zoneinfo->fReverse) {
1174                                                 found2 = true;
1175                                         }
1176                                 }
1177                                 if (rin->Dword & DNS_ZONE_REQUEST_FORWARDER) {
1178                                         if (z->zoneinfo->dwZoneType == DNS_ZONE_TYPE_FORWARDER) {
1179                                                 found2 = true;
1180                                         }
1181                                 }
1182                                 if (rin->Dword & DNS_ZONE_REQUEST_STUB) {
1183                                         if (z->zoneinfo->dwZoneType == DNS_ZONE_TYPE_STUB) {
1184                                                 found2 = true;
1185                                         }
1186                                 }
1187                         } else {
1188                                 found2 = true;
1189                         }
1190
1191                         /* Group 3 */
1192                         found3 = false;
1193                         if (rin->Dword & 0x00000f00) {
1194                                 if (rin->Dword & DNS_ZONE_REQUEST_DS) {
1195                                         if (z->zoneinfo->Flags & DNS_RPC_ZONE_DSINTEGRATED) {
1196                                                 found3 = true;
1197                                         }
1198                                 }
1199                                 if (rin->Dword & DNS_ZONE_REQUEST_NON_DS) {
1200                                         if (!(z->zoneinfo->Flags & DNS_RPC_ZONE_DSINTEGRATED)) {
1201                                                 found3 = true;
1202                                         }
1203                                 }
1204                                 if (rin->Dword & DNS_ZONE_REQUEST_DOMAIN_DP) {
1205                                         if (!(z->zoneinfo->dwDpFlags & DNS_DP_DOMAIN_DEFAULT)) {
1206                                                 found3 = true;
1207                                         }
1208                                 }
1209                                 if (rin->Dword & DNS_ZONE_REQUEST_FOREST_DP) {
1210                                         if (!(z->zoneinfo->dwDpFlags & DNS_DP_FOREST_DEFAULT)) {
1211                                                 found3 = true;
1212                                         }
1213                                 }
1214                         } else {
1215                                 found3 = true;
1216                         }
1217         
1218                         /* Group 4 */
1219                         if (rin->Dword & 0x0000f000) {
1220                                 found4 = false;
1221                         } else {
1222                                 found4 = true;
1223                         }
1224
1225                         if (found1 && found2 && found3 && found4) {
1226                                 zlist = talloc_realloc(mem_ctx, zlist, struct dnsserver_zone *, zcount+1);
1227                                 zlist[zcount] = z;
1228                                 zcount++;
1229                         }
1230                 }
1231
1232                 if (client_version == DNS_CLIENT_VERSION_W2K) {
1233                         *typeid_out = DNSSRV_TYPEID_ZONE_LIST_W2K;
1234                         rout->ZoneListW2K = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_LIST_W2K);
1235
1236                         if (zcount == 0) {
1237                                 rout->ZoneListW2K->dwZoneCount = 0;
1238                                 rout->ZoneListW2K->ZoneArray = NULL;
1239
1240                                 return WERR_OK;
1241                         }
1242
1243                         rout->ZoneListW2K->ZoneArray = talloc_zero_array(mem_ctx, struct DNS_RPC_ZONE_W2K *, zcount);
1244                         if (rout->ZoneListW2K->ZoneArray == NULL) {
1245                                 talloc_free(zlist);
1246                                 return WERR_NOMEM;
1247                         }
1248
1249                         for (i=0; i<zcount; i++) {
1250                                 rout->ZoneListW2K->ZoneArray[i] = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_W2K);
1251
1252                                 rout->ZoneListW2K->ZoneArray[i]->pszZoneName = talloc_strdup(mem_ctx, zlist[i]->name);
1253                                 rout->ZoneListW2K->ZoneArray[i]->Flags = zlist[i]->zoneinfo->Flags;
1254                                 rout->ZoneListW2K->ZoneArray[i]->ZoneType = zlist[i]->zoneinfo->dwZoneType;
1255                                 rout->ZoneListW2K->ZoneArray[i]->Version = zlist[i]->zoneinfo->Version;
1256                         }
1257                         rout->ZoneListW2K->dwZoneCount = zcount;
1258
1259                 } else {
1260                         *typeid_out = DNSSRV_TYPEID_ZONE_LIST;
1261                         rout->ZoneList = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_LIST_DOTNET);
1262
1263                         if (zcount == 0) {
1264                                 rout->ZoneList->dwRpcStructureVersion = 1;
1265                                 rout->ZoneList->dwZoneCount = 0;
1266                                 rout->ZoneList->ZoneArray = NULL;
1267
1268                                 return WERR_OK;
1269                         }
1270
1271                         rout->ZoneList->ZoneArray = talloc_zero_array(mem_ctx, struct DNS_RPC_ZONE_DOTNET *, zcount);
1272                         if (rout->ZoneList->ZoneArray == NULL) {
1273                                 talloc_free(zlist);
1274                                 return WERR_NOMEM;
1275                         }
1276
1277                         for (i=0; i<zcount; i++) {
1278                                 rout->ZoneList->ZoneArray[i] = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_DOTNET);
1279
1280                                 rout->ZoneList->ZoneArray[i]->dwRpcStructureVersion = 1;
1281                                 rout->ZoneList->ZoneArray[i]->pszZoneName = talloc_strdup(mem_ctx, zlist[i]->name);
1282                                 rout->ZoneList->ZoneArray[i]->Flags = zlist[i]->zoneinfo->Flags;
1283                                 rout->ZoneList->ZoneArray[i]->ZoneType = zlist[i]->zoneinfo->dwZoneType;
1284                                 rout->ZoneList->ZoneArray[i]->Version = zlist[i]->zoneinfo->Version;
1285                                 rout->ZoneList->ZoneArray[i]->dwDpFlags = zlist[i]->zoneinfo->dwDpFlags;
1286                                 rout->ZoneList->ZoneArray[i]->pszDpFqdn = talloc_strdup(mem_ctx, zlist[i]->zoneinfo->pszDpFqdn);
1287                         }
1288                         rout->ZoneList->dwRpcStructureVersion = 1;
1289                         rout->ZoneList->dwZoneCount = zcount;
1290                 }
1291                 talloc_free(zlist);
1292                 return WERR_OK;
1293         } else if (strcasecmp(operation, "EnumZones2") == 0) {
1294                 valid_operation = true;
1295         } else if (strcasecmp(operation, "EnumDirectoryPartitions") == 0) {
1296                 valid_operation = true;
1297         } else if (strcasecmp(operation, "DirectoryPartitionInfo") == 0) {
1298                 valid_operation = true;
1299         } else if (strcasecmp(operation, "Statistics") == 0) {
1300                 valid_operation = true;
1301         } else if (strcasecmp(operation, "IpValidate") == 0) {
1302                 valid_operation = true;
1303         }
1304
1305         if (valid_operation) {
1306                 DEBUG(0, ("dnsserver: server complex operation '%s' not implemented", operation));
1307                 return WERR_CALL_NOT_IMPLEMENTED;
1308         }
1309
1310         DEBUG(0, ("dnsserver: invalid server complex operation '%s'", operation));
1311         return WERR_DNS_ERROR_INVALID_PROPERTY;
1312 }
1313
1314 /* [MS-DNSP].pdf Section 3.1.1.2 Zone Configuration Information */
1315 static WERROR dnsserver_operate_zone(struct dnsserver_state *dsstate,
1316                                         TALLOC_CTX *mem_ctx,
1317                                         struct dnsserver_zone *z,
1318                                         unsigned int request_filter,
1319                                         const char *operation,
1320                                         const unsigned int client_version,
1321                                         enum DNS_RPC_TYPEID typeid,
1322                                         union DNSSRV_RPC_UNION *r)
1323 {
1324         bool valid_operation = false;
1325
1326         if (strcasecmp(operation, "ResetDwordProperty") == 0) {
1327                 valid_operation = true;
1328         } else if (strcasecmp(operation, "ZoneTypeReset") == 0) {
1329                 valid_operation = true;
1330         } else if (strcasecmp(operation, "PauseZone") == 0) {
1331                 valid_operation = true;
1332         } else if (strcasecmp(operation, "ResumeZone") == 0) {
1333                 valid_operation = true;
1334         } else if (strcasecmp(operation, "DeleteZone") == 0) {
1335                 valid_operation = true;
1336         } else if (strcasecmp(operation, "ReloadZone") == 0) {
1337                 valid_operation = true;
1338         } else if (strcasecmp(operation, "RefreshZone") == 0) {
1339                 valid_operation = true;
1340         } else if (strcasecmp(operation, "ExpireZone") == 0) {
1341                 valid_operation = true;
1342         } else if (strcasecmp(operation, "IncrementVersion") == 0) {
1343                 valid_operation = true;
1344         } else if (strcasecmp(operation, "WriteBackFile") == 0) {
1345                 valid_operation = true;
1346         } else if (strcasecmp(operation, "DeleteZoneFromDs") == 0) {
1347                 valid_operation = true;
1348         } else if (strcasecmp(operation, "UpdateZoneFromDs") == 0) {
1349                 valid_operation = true;
1350         } else if (strcasecmp(operation, "ZoneExport") == 0) {
1351                 valid_operation = true;
1352         } else if (strcasecmp(operation, "ZoneChangeDirectoryPartition") == 0) {
1353                 valid_operation = true;
1354         } else if (strcasecmp(operation, "DeleteNode") == 0) {
1355                 valid_operation = true;
1356         } else if (strcasecmp(operation, "DeleteRecordSet") == 0) {
1357                 valid_operation = true;
1358         } else if (strcasecmp(operation, "ForceAgingOnNode") == 0) {
1359                 valid_operation = true;
1360         } else if (strcasecmp(operation, "DatabaseFile") == 0) {
1361                 valid_operation = true;
1362         } else if (strcasecmp(operation, "MasterServers") == 0) {
1363                 valid_operation = true;
1364         } else if (strcasecmp(operation, "LocalMasterServers") == 0) {
1365                 valid_operation = true;
1366         } else if (strcasecmp(operation, "NotifyServers") == 0) {
1367                 valid_operation = true;
1368         } else if (strcasecmp(operation, "SecondaryServers") == 0) {
1369                 valid_operation = true;
1370         } else if (strcasecmp(operation, "ScavengingServers") == 0) {
1371                 valid_operation = true;
1372         } else if (strcasecmp(operation, "AllowNSRecordsAutoCreation") == 0) {
1373                 valid_operation = true;
1374         } else if (strcasecmp(operation, "BreakOnNameUpdate") == 0) {
1375                 valid_operation = true;
1376         } else if (strcasecmp(operation, "ApplicationDirectoryPartition") == 0) {
1377                 valid_operation = true;
1378         }
1379
1380         if (valid_operation) {
1381                 DEBUG(0, ("dnsserver: zone operation '%s' not implemented", operation));
1382                 return WERR_CALL_NOT_IMPLEMENTED;
1383         }
1384
1385         DEBUG(0, ("dnsserver: invalid zone operation '%s'", operation));
1386         return WERR_DNS_ERROR_INVALID_PROPERTY;
1387 }
1388
1389 static WERROR dnsserver_complex_operate_zone(struct dnsserver_state *dsstate,
1390                                         TALLOC_CTX *mem_ctx,
1391                                         struct dnsserver_zone *z,
1392                                         const char *operation,
1393                                         const unsigned int client_version,
1394                                         enum DNS_RPC_TYPEID typeid_in,
1395                                         union DNSSRV_RPC_UNION *rin,
1396                                         enum DNS_RPC_TYPEID *typeid_out,
1397                                         union DNSSRV_RPC_UNION *rout)
1398 {
1399         if (strcasecmp(operation, "QueryDwordProperty") == 0) {
1400                 if (typeid_in == DNSSRV_TYPEID_LPSTR) {
1401                         return dnsserver_query_zone(dsstate, mem_ctx, z,
1402                                                 rin->String,
1403                                                 client_version,
1404                                                 typeid_out,
1405                                                 rout);
1406
1407                 }
1408         }
1409
1410         DEBUG(0,("dnsserver: Invalid zone operation %s", operation));
1411         return WERR_DNS_ERROR_INVALID_PROPERTY;
1412 }
1413
1414 /* dnsserver enumerate function */
1415
1416 static WERROR dnsserver_enumerate_root_records(struct dnsserver_state *dsstate,
1417                                         TALLOC_CTX *mem_ctx,
1418                                         unsigned int client_version,
1419                                         const char *node_name,
1420                                         enum dns_record_type record_type,
1421                                         unsigned int select_flag,
1422                                         unsigned int *buffer_length,
1423                                         struct DNS_RPC_RECORDS_ARRAY **buffer)
1424 {
1425         TALLOC_CTX *tmp_ctx;
1426         const char * const attrs[] = { "name", "dnsRecord", NULL };
1427         struct ldb_result *res;
1428         struct ldb_dn *dn;
1429         struct DNS_RPC_RECORDS_ARRAY *recs;
1430         char **add_names;
1431         char *rname;
1432         int add_count;
1433         int i, ret, len;
1434         WERROR status;
1435
1436         tmp_ctx = talloc_new(mem_ctx);
1437         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1438
1439         dn = ldb_dn_copy(tmp_ctx, ldb_get_default_basedn(dsstate->samdb));
1440         W_ERROR_HAVE_NO_MEMORY_AND_FREE(dn, tmp_ctx);
1441
1442         if (!ldb_dn_add_child_fmt(dn, "DC=RootDNSServers,CN=MicrosoftDNS,DC=DomainDnsZones")) {
1443                 talloc_free(tmp_ctx);
1444                 return WERR_NOMEM;
1445         }
1446
1447         ret = ldb_search(dsstate->samdb, tmp_ctx, &res, dn,
1448                                 LDB_SCOPE_ONELEVEL, attrs, "(&(objectClass=dnsNode)(name=@))");
1449         if (ret != LDB_SUCCESS) {
1450                 talloc_free(tmp_ctx);
1451                 return WERR_INTERNAL_DB_ERROR;
1452         }
1453         if (res->count == 0) {
1454                 talloc_free(tmp_ctx);
1455                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1456         }
1457
1458         recs = talloc_zero(mem_ctx, struct DNS_RPC_RECORDS_ARRAY);
1459         W_ERROR_HAVE_NO_MEMORY_AND_FREE(recs, tmp_ctx);
1460
1461         add_names = NULL;
1462         add_count = 0;
1463
1464         for (i=0; i<res->count; i++) {
1465                 status = dns_fill_records_array(tmp_ctx, NULL, record_type,
1466                                                 select_flag, NULL,
1467                                                 res->msgs[i], 0, recs,
1468                                                 &add_names, &add_count);
1469                 if (!W_ERROR_IS_OK(status)) {
1470                         talloc_free(tmp_ctx);
1471                         return status;
1472                 }
1473         }
1474         talloc_free(res);
1475
1476         /* Add any additional records */
1477         if (select_flag & DNS_RPC_VIEW_ADDITIONAL_DATA) {
1478                 for (i=0; i<add_count; i++) {
1479                         ret = ldb_search(dsstate->samdb, tmp_ctx, &res, dn,
1480                                         LDB_SCOPE_ONELEVEL, attrs,
1481                                         "(&(objectClass=dnsNode)(name=%s))", add_names[i]);
1482                         if (ret != LDB_SUCCESS || res->count == 0) {
1483                                 talloc_free(res);
1484                                 continue;
1485                         }
1486
1487                         len = strlen(add_names[i]);
1488                         if (add_names[i][len-1] == '.') {
1489                                 rname = talloc_strdup(tmp_ctx, add_names[i]);
1490                         } else {
1491                                 rname = talloc_asprintf(tmp_ctx, "%s.", add_names[i]);
1492                         }
1493                         status = dns_fill_records_array(tmp_ctx, NULL, DNS_TYPE_A,
1494                                                         select_flag, rname,
1495                                                         res->msgs[0], 0, recs,
1496                                                         NULL, NULL);
1497                         talloc_free(rname);
1498                         talloc_free(res);
1499                 }
1500         }
1501
1502         talloc_free(tmp_ctx);
1503
1504         *buffer_length = ndr_size_DNS_RPC_RECORDS_ARRAY(recs, 0);
1505         *buffer = recs;
1506
1507         return WERR_OK;
1508 }
1509
1510
1511 static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate,
1512                                         TALLOC_CTX *mem_ctx,
1513                                         struct dnsserver_zone *z,
1514                                         unsigned int client_version,
1515                                         const char *node_name,
1516                                         const char *start_child,
1517                                         enum dns_record_type record_type,
1518                                         unsigned int select_flag,
1519                                         const char *filter_start,
1520                                         const char *filter_stop,
1521                                         unsigned int *buffer_length,
1522                                         struct DNS_RPC_RECORDS_ARRAY **buffer)
1523 {
1524         TALLOC_CTX *tmp_ctx;
1525         char *name;
1526         const char * const attrs[] = { "name", "dnsRecord", NULL };
1527         struct ldb_result *res;
1528         struct DNS_RPC_RECORDS_ARRAY *recs;
1529         char **add_names = NULL;
1530         char *rname;
1531         int add_count = 0;
1532         int i, ret, len;
1533         WERROR status;
1534         struct dns_tree *tree, *base, *node;
1535
1536         tmp_ctx = talloc_new(mem_ctx);
1537         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1538
1539         name = dns_split_node_name(tmp_ctx, node_name, z->name);
1540         W_ERROR_HAVE_NO_MEMORY_AND_FREE(name, tmp_ctx);
1541
1542         /* search all records under parent tree */
1543         if (strcmp(name, z->name) == 0) {
1544                 ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z->zone_dn,
1545                                 LDB_SCOPE_ONELEVEL, attrs, "(objectClass=dnsNode)");
1546         } else {
1547                 ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z->zone_dn,
1548                                 LDB_SCOPE_ONELEVEL, attrs,
1549                                 "(&(objectClass=dnsNode)(|(name=%s)(name=*.%s)))",
1550                                 name, name);
1551         }
1552         if (ret != LDB_SUCCESS) {
1553                 talloc_free(tmp_ctx);
1554                 return WERR_INTERNAL_DB_ERROR;
1555         }
1556         if (res->count == 0) {
1557                 talloc_free(tmp_ctx);
1558                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1559         }
1560
1561         recs = talloc_zero(mem_ctx, struct DNS_RPC_RECORDS_ARRAY);
1562         W_ERROR_HAVE_NO_MEMORY_AND_FREE(recs, tmp_ctx);
1563
1564         /* Sort the names, so that the first record is the parent record */
1565         ldb_qsort(res->msgs, res->count, sizeof(struct ldb_message *), name,
1566                         (ldb_qsort_cmp_fn_t)dns_name_compare);
1567
1568         /* Build a tree of name components from dns name */
1569         if (strcmp(name, z->name) == 0) {
1570                 tree = dns_build_tree(tmp_ctx, "@", res);
1571         } else {
1572                 tree = dns_build_tree(tmp_ctx, name, res);
1573         }
1574         W_ERROR_HAVE_NO_MEMORY_AND_FREE(tree, tmp_ctx);
1575
1576         /* Find the parent record in the tree */
1577         base = tree;
1578         while (base->level != -1) {
1579                 base = base->children[0];
1580         }
1581
1582         /* Add the parent record with blank name */
1583         if (!(select_flag & DNS_RPC_VIEW_ONLY_CHILDREN)) {
1584                 status = dns_fill_records_array(tmp_ctx, z, record_type,
1585                                                 select_flag, NULL,
1586                                                 base->data, 0,
1587                                                 recs, &add_names, &add_count);
1588                 if (!W_ERROR_IS_OK(status)) {
1589                         talloc_free(tmp_ctx);
1590                         return status;
1591                 }
1592         }
1593
1594         /* Add all the children records */
1595         if (!(select_flag & DNS_RPC_VIEW_NO_CHILDREN)) {
1596                 for (i=0; i<base->num_children; i++) {
1597                         node = base->children[i];
1598
1599                         status = dns_fill_records_array(tmp_ctx, z, record_type,
1600                                                         select_flag, node->name,
1601                                                         node->data, node->num_children,
1602                                                         recs, &add_names, &add_count);
1603                         if (!W_ERROR_IS_OK(status)) {
1604                                 talloc_free(tmp_ctx);
1605                                 return status;
1606                         }
1607                 }
1608         }
1609
1610         talloc_free(res);
1611         talloc_free(tree);
1612         talloc_free(name);
1613
1614         /* Add any additional records */
1615         if (select_flag & DNS_RPC_VIEW_ADDITIONAL_DATA) {
1616                 for (i=0; i<add_count; i++) {
1617                         struct dnsserver_zone *z2;
1618
1619                         /* Search all the available zones for additional name */
1620                         for (z2 = dsstate->zones; z2; z2 = z2->next) {
1621                                 name = dns_split_node_name(tmp_ctx, add_names[i], z2->name);
1622                                 ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z2->zone_dn,
1623                                                 LDB_SCOPE_ONELEVEL, attrs,
1624                                                 "(&(objectClass=dnsNode)(name=%s))", name);
1625                                 talloc_free(name);
1626                                 if (ret != LDB_SUCCESS) {
1627                                         continue;
1628                                 }
1629                                 if (res->count == 1) {
1630                                         break;
1631                                 } else {
1632                                         talloc_free(res);
1633                                         continue;
1634                                 }
1635                         }
1636
1637                         len = strlen(add_names[i]);
1638                         if (add_names[i][len-1] == '.') {
1639                                 rname = talloc_strdup(tmp_ctx, add_names[i]);
1640                         } else {
1641                                 rname = talloc_asprintf(tmp_ctx, "%s.", add_names[i]);
1642                         }
1643                         status = dns_fill_records_array(tmp_ctx, NULL, DNS_TYPE_A,
1644                                                         select_flag, rname,
1645                                                         res->msgs[0], 0, recs,
1646                                                         NULL, NULL);
1647                         talloc_free(rname);
1648                         talloc_free(res);
1649                 }
1650         }
1651
1652         *buffer_length = ndr_size_DNS_RPC_RECORDS_ARRAY(recs, 0);
1653         *buffer = recs;
1654
1655         return WERR_OK;
1656 }
1657
1658 /* dnsserver update function */
1659
1660 static WERROR dnsserver_update_record(struct dnsserver_state *dsstate,
1661                                         TALLOC_CTX *mem_ctx,
1662                                         struct dnsserver_zone *z,
1663                                         unsigned int client_version,
1664                                         const char *node_name,
1665                                         struct DNS_RPC_RECORD_BUF *add_buf,
1666                                         struct DNS_RPC_RECORD_BUF *del_buf)
1667 {
1668         TALLOC_CTX *tmp_ctx;
1669         char *name;
1670         WERROR status;
1671
1672         tmp_ctx = talloc_new(mem_ctx);
1673         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1674
1675         name = dns_split_node_name(tmp_ctx, node_name, z->name);
1676         W_ERROR_HAVE_NO_MEMORY_AND_FREE(name, tmp_ctx);
1677
1678         if (add_buf != NULL) {
1679                 if (del_buf == NULL) {
1680                         /* Add record */
1681                         status = dnsserver_db_add_record(tmp_ctx, dsstate->samdb,
1682                                                                 z, name,
1683                                                                 &add_buf->rec);
1684                 } else {
1685                         /* Update record */
1686                         status = dnsserver_db_update_record(tmp_ctx, dsstate->samdb,
1687                                                                 z, name,
1688                                                                 &add_buf->rec,
1689                                                                 &del_buf->rec);
1690                 }
1691         } else {
1692                 if (del_buf == NULL) {
1693                         /* Add empty node */
1694                         status = dnsserver_db_add_empty_node(tmp_ctx, dsstate->samdb,
1695                                                                 z, name);
1696                 } else {
1697                         /* Delete record */
1698                         status = dnsserver_db_delete_record(tmp_ctx, dsstate->samdb,
1699                                                                 z, name,
1700                                                                 &del_buf->rec);
1701                 }
1702         }
1703
1704         talloc_free(tmp_ctx);
1705         return status;
1706 }
1707
1708
1709 /* dnsserver interface functions */
1710
1711 static WERROR dcesrv_DnssrvOperation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvOperation *r)
1712 {
1713         struct dnsserver_state *dsstate;
1714         struct dnsserver_zone *z = NULL;
1715         uint32_t request_filter = 0;
1716         WERROR ret;
1717
1718         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1719                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1720         }
1721
1722         if (r->in.dwContext == 0) {
1723                 if (r->in.pszZone != NULL) {
1724                         request_filter = dnsserver_zone_to_request_filter(r->in.pszZone);
1725                 }
1726         } else {
1727                 request_filter = r->in.dwContext;
1728         }
1729
1730         if (r->in.pszZone == NULL) {
1731                 ret = dnsserver_operate_server(dsstate, mem_ctx,
1732                                                 r->in.pszOperation,
1733                                                 DNS_CLIENT_VERSION_W2K,
1734                                                 r->in.dwTypeId,
1735                                                 &r->in.pData);
1736         } else {
1737                 ret = dnsserver_operate_zone(dsstate, mem_ctx, z,
1738                                                 request_filter,
1739                                                 r->in.pszOperation,
1740                                                 DNS_CLIENT_VERSION_W2K,
1741                                                 r->in.dwTypeId,
1742                                                 &r->in.pData);
1743         }
1744
1745         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1746                 NDR_PRINT_FUNCTION_DEBUG(DnssrvOperation, NDR_IN, r);
1747         }
1748         return ret;
1749 }
1750
1751 static WERROR dcesrv_DnssrvQuery(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvQuery *r)
1752 {
1753         struct dnsserver_state *dsstate;
1754         struct dnsserver_zone *z;
1755         WERROR ret;
1756
1757         ZERO_STRUCTP(r->out.pdwTypeId);
1758         ZERO_STRUCTP(r->out.ppData);
1759
1760         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1761                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1762         }
1763
1764         if (r->in.pszZone == NULL) {
1765                 /* FIXME: DNS Server Configuration Access Control List */
1766                 ret = dnsserver_query_server(dsstate, mem_ctx,
1767                                                 r->in.pszOperation,
1768                                                 DNS_CLIENT_VERSION_W2K,
1769                                                 r->out.pdwTypeId,
1770                                                 r->out.ppData);
1771         } else {
1772                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
1773                 if (z == NULL) {
1774                         return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
1775                 }
1776
1777                 ret = dnsserver_query_zone(dsstate, mem_ctx, z,
1778                                                 r->in.pszOperation,
1779                                                 DNS_CLIENT_VERSION_W2K,
1780                                                 r->out.pdwTypeId,
1781                                                 r->out.ppData);
1782         }
1783
1784         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1785                 NDR_PRINT_FUNCTION_DEBUG(DnssrvQuery, NDR_IN, r);
1786         }
1787         return ret;
1788 }
1789
1790 static WERROR dcesrv_DnssrvComplexOperation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvComplexOperation *r)
1791 {
1792         struct dnsserver_state *dsstate;
1793         struct dnsserver_zone *z;
1794         WERROR ret;
1795
1796         ZERO_STRUCTP(r->out.pdwTypeOut);
1797         ZERO_STRUCTP(r->out.ppDataOut);
1798
1799         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1800                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1801         }
1802
1803         if (r->in.pszZone == NULL) {
1804                 /* Server operation */
1805                 ret = dnsserver_complex_operate_server(dsstate, mem_ctx,
1806                                                         r->in.pszOperation,
1807                                                         DNS_CLIENT_VERSION_W2K,
1808                                                         r->in.dwTypeIn,
1809                                                         &r->in.pDataIn,
1810                                                         r->out.pdwTypeOut,
1811                                                         r->out.ppDataOut);
1812         } else {
1813                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
1814                 if (z == NULL) {
1815                         return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
1816                 }
1817
1818                 ret = dnsserver_complex_operate_zone(dsstate, mem_ctx, z,
1819                                                         r->in.pszOperation,
1820                                                         DNS_CLIENT_VERSION_W2K,
1821                                                         r->in.dwTypeIn,
1822                                                         &r->in.pDataIn,
1823                                                         r->out.pdwTypeOut,
1824                                                         r->out.ppDataOut);
1825         }
1826
1827         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1828                 NDR_PRINT_FUNCTION_DEBUG(DnssrvComplexOperation, NDR_IN, r);
1829         }
1830         return ret;
1831 }
1832
1833 static WERROR dcesrv_DnssrvEnumRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvEnumRecords *r)
1834 {
1835         struct dnsserver_state *dsstate;
1836         struct dnsserver_zone *z;
1837         WERROR ret;
1838
1839         ZERO_STRUCTP(r->out.pdwBufferLength);
1840         ZERO_STRUCTP(r->out.pBuffer);
1841
1842         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1843                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1844         }
1845
1846         if (r->in.pszZone == NULL) {
1847                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1848         }
1849
1850         if (strcasecmp(r->in.pszZone, "..RootHints") == 0) {
1851                 ret = dnsserver_enumerate_root_records(dsstate, mem_ctx,
1852                                         DNS_CLIENT_VERSION_W2K,
1853                                         r->in.pszNodeName,
1854                                         r->in.wRecordType,
1855                                         r->in.fSelectFlag,
1856                                         r->out.pdwBufferLength,
1857                                         r->out.pBuffer);
1858         } else {
1859                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
1860                 if (z == NULL) {
1861                         return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1862                 }
1863
1864                 ret = dnsserver_enumerate_records(dsstate, mem_ctx, z,
1865                                         DNS_CLIENT_VERSION_W2K,
1866                                         r->in.pszNodeName,
1867                                         r->in.pszStartChild,
1868                                         r->in.wRecordType,
1869                                         r->in.fSelectFlag,
1870                                         r->in.pszFilterStart,
1871                                         r->in.pszFilterStop,
1872                                         r->out.pdwBufferLength,
1873                                         r->out.pBuffer);
1874         }
1875
1876         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1877                 NDR_PRINT_FUNCTION_DEBUG(DnssrvEnumRecords, NDR_IN, r);
1878         }
1879         return ret;
1880 }
1881
1882 static WERROR dcesrv_DnssrvUpdateRecord(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvUpdateRecord *r)
1883 {
1884         struct dnsserver_state *dsstate;
1885         struct dnsserver_zone *z;
1886         WERROR ret;
1887
1888         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1889                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1890         }
1891
1892         if (r->in.pszZone == NULL) {
1893                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1894         }
1895
1896         z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
1897         if (z == NULL) {
1898                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1899         }
1900
1901         ret = dnsserver_update_record(dsstate, mem_ctx, z,
1902                                         DNS_CLIENT_VERSION_W2K,
1903                                         r->in.pszNodeName,
1904                                         r->in.pAddRecord,
1905                                         r->in.pDeleteRecord);
1906
1907         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1908                 NDR_PRINT_FUNCTION_DEBUG(DnssrvUpdateRecord, NDR_IN, r);
1909         }
1910         return ret;
1911 }
1912
1913 static WERROR dcesrv_DnssrvOperation2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvOperation2 *r)
1914 {
1915         struct dnsserver_state *dsstate;
1916         struct dnsserver_zone *z = NULL;
1917         uint32_t request_filter = 0;
1918         WERROR ret;
1919
1920         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1921                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1922         }
1923
1924         if (r->in.dwContext == 0) {
1925                 if (r->in.pszZone != NULL) {
1926                         request_filter = dnsserver_zone_to_request_filter(r->in.pszZone);
1927                 }
1928         } else {
1929                 request_filter = r->in.dwContext;
1930         }
1931
1932         if (r->in.pszZone == NULL) {
1933                 ret = dnsserver_operate_server(dsstate, mem_ctx,
1934                                                 r->in.pszOperation,
1935                                                 r->in.dwClientVersion,
1936                                                 r->in.dwTypeId,
1937                                                 &r->in.pData);
1938         } else {
1939                 ret = dnsserver_operate_zone(dsstate, mem_ctx, z,
1940                                                 request_filter,
1941                                                 r->in.pszOperation,
1942                                                 r->in.dwClientVersion,
1943                                                 r->in.dwTypeId,
1944                                                 &r->in.pData);
1945         }
1946
1947         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1948                 NDR_PRINT_FUNCTION_DEBUG(DnssrvOperation2, NDR_IN, r);
1949         }
1950         return ret;
1951 }
1952
1953 static WERROR dcesrv_DnssrvQuery2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvQuery2 *r)
1954 {
1955         struct dnsserver_state *dsstate;
1956         struct dnsserver_zone *z;
1957         WERROR ret;
1958
1959         ZERO_STRUCTP(r->out.pdwTypeId);
1960         ZERO_STRUCTP(r->out.ppData);
1961
1962         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1963                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1964         }
1965
1966         if (r->in.pszZone == NULL) {
1967                 /* FIXME: DNS Server Configuration Access Control List */
1968                 ret = dnsserver_query_server(dsstate, mem_ctx,
1969                                                 r->in.pszOperation,
1970                                                 r->in.dwClientVersion,
1971                                                 r->out.pdwTypeId,
1972                                                 r->out.ppData);
1973         } else {
1974                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
1975                 if (z == NULL) {
1976                         return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
1977                 }
1978
1979                 ret = dnsserver_query_zone(dsstate, mem_ctx, z,
1980                                         r->in.pszOperation,
1981                                         r->in.dwClientVersion,
1982                                         r->out.pdwTypeId,
1983                                         r->out.ppData);
1984         }
1985
1986         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1987                 NDR_PRINT_FUNCTION_DEBUG(DnssrvQuery2, NDR_IN, r);
1988         }
1989         return ret;
1990 }
1991
1992 static WERROR dcesrv_DnssrvComplexOperation2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvComplexOperation2 *r)
1993 {
1994         struct dnsserver_state *dsstate;
1995         struct dnsserver_zone *z;
1996         WERROR ret;
1997
1998         ZERO_STRUCTP(r->out.pdwTypeOut);
1999         ZERO_STRUCTP(r->out.ppDataOut);
2000
2001         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
2002                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
2003         }
2004
2005         if (r->in.pszZone == NULL) {
2006                 /* Server operation */
2007                 ret =  dnsserver_complex_operate_server(dsstate, mem_ctx,
2008                                                         r->in.pszOperation,
2009                                                         r->in.dwClientVersion,
2010                                                         r->in.dwTypeIn,
2011                                                         &r->in.pDataIn,
2012                                                         r->out.pdwTypeOut,
2013                                                         r->out.ppDataOut);
2014         } else {
2015
2016                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
2017                 if (z == NULL) {
2018                         return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
2019                 }
2020
2021                 ret = dnsserver_complex_operate_zone(dsstate, mem_ctx, z,
2022                                                         r->in.pszOperation,
2023                                                         r->in.dwClientVersion,
2024                                                         r->in.dwTypeIn,
2025                                                         &r->in.pDataIn,
2026                                                         r->out.pdwTypeOut,
2027                                                         r->out.ppDataOut);
2028         }
2029
2030         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2031                 NDR_PRINT_FUNCTION_DEBUG(DnssrvComplexOperation2, NDR_IN, r);
2032         }
2033         return ret;
2034 }
2035
2036 static WERROR dcesrv_DnssrvEnumRecords2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvEnumRecords2 *r)
2037 {
2038         struct dnsserver_state *dsstate;
2039         struct dnsserver_zone *z;
2040         WERROR ret;
2041
2042         ZERO_STRUCTP(r->out.pdwBufferLength);
2043         ZERO_STRUCTP(r->out.pBuffer);
2044
2045         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
2046                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
2047         }
2048
2049         if (r->in.pszZone == NULL) {
2050                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2051         }
2052
2053         if (strcasecmp(r->in.pszZone, "..RootHints") == 0) {
2054                 ret =  dnsserver_enumerate_root_records(dsstate, mem_ctx,
2055                                         r->in.dwClientVersion,
2056                                         r->in.pszNodeName,
2057                                         r->in.wRecordType,
2058                                         r->in.fSelectFlag,
2059                                         r->out.pdwBufferLength,
2060                                         r->out.pBuffer);
2061         } else {
2062                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
2063                 if (z == NULL) {
2064                         return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2065                 }
2066
2067                 ret =  dnsserver_enumerate_records(dsstate, mem_ctx, z,
2068                                         r->in.dwClientVersion,
2069                                         r->in.pszNodeName,
2070                                         r->in.pszStartChild,
2071                                         r->in.wRecordType,
2072                                         r->in.fSelectFlag,
2073                                         r->in.pszFilterStart,
2074                                         r->in.pszFilterStop,
2075                                         r->out.pdwBufferLength,
2076                                         r->out.pBuffer);
2077
2078         }
2079
2080         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2081                 NDR_PRINT_FUNCTION_DEBUG(DnssrvEnumRecords2, NDR_IN, r);
2082         }
2083         return ret;
2084 }
2085
2086 static WERROR dcesrv_DnssrvUpdateRecord2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvUpdateRecord2 *r)
2087 {
2088         struct dnsserver_state *dsstate;
2089         struct dnsserver_zone *z;
2090         WERROR ret;
2091
2092         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
2093                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
2094         }
2095
2096         if (r->in.pszZone == NULL) {
2097                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2098         }
2099
2100         z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
2101         if (z == NULL) {
2102                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2103         }
2104
2105         ret = dnsserver_update_record(dsstate, mem_ctx, z,
2106                                         r->in.dwClientVersion,
2107                                         r->in.pszNodeName,
2108                                         r->in.pAddRecord,
2109                                         r->in.pDeleteRecord);
2110
2111         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2112                 NDR_PRINT_FUNCTION_DEBUG(DnssrvUpdateRecord2, NDR_IN, r);
2113         }
2114         return ret;
2115 }
2116
2117 /* include the generated boilerplate */
2118 #include "librpc/gen_ndr/ndr_dnsserver_s.c"