s4-dnsserver: List dns zones matching the search filter
[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 found;
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                         found = false;
1128                         if (rin->Dword & DNS_ZONE_REQUEST_PRIMARY) {
1129                                 if (z->zoneinfo->dwZoneType & DNS_ZONE_TYPE_PRIMARY) {
1130                                         found = true;
1131                                 }
1132                         }
1133                         if (rin->Dword & DNS_ZONE_REQUEST_SECONDARY) {
1134                                 if (z->zoneinfo->dwZoneType & DNS_ZONE_TYPE_SECONDARY) {
1135                                         found = true;
1136                                 }
1137                         }
1138                         if (rin->Dword & DNS_ZONE_REQUEST_CACHE) {
1139                                 if (z->zoneinfo->dwZoneType & DNS_ZONE_TYPE_CACHE) {
1140                                         found = true;
1141                                 }
1142                         }
1143                         if (rin->Dword & DNS_ZONE_REQUEST_AUTO) {
1144                                 if (z->zoneinfo->fAutoCreated || z->zoneinfo->dwDpFlags & DNS_DP_AUTOCREATED) {
1145                                         found = true;
1146                                 }
1147                         }
1148                         if (rin->Dword & DNS_ZONE_REQUEST_FORWARD) {
1149                                 if (!(z->zoneinfo->Flags & DNS_RPC_ZONE_REVERSE)) {
1150                                         found = true;
1151                                 }
1152                         }
1153                         if (rin->Dword & DNS_ZONE_REQUEST_REVERSE) {
1154                                 if (z->zoneinfo->Flags & DNS_RPC_ZONE_REVERSE) {
1155                                         found = true;
1156                                 }
1157                         }
1158                         if (rin->Dword & DNS_ZONE_REQUEST_FORWARDER) {
1159                                 if (z->zoneinfo->dwZoneType & DNS_ZONE_TYPE_FORWARDER) {
1160                                         found = true;
1161                                 }
1162                         }
1163                         if (rin->Dword & DNS_ZONE_REQUEST_STUB) {
1164                                 if (z->zoneinfo->dwZoneType & DNS_ZONE_TYPE_STUB) {
1165                                         found = true;
1166                                 }
1167                         }
1168                         if (rin->Dword & DNS_ZONE_REQUEST_DS) {
1169                                 if (z->zoneinfo->Flags & DNS_RPC_ZONE_DSINTEGRATED) {
1170                                         found = true;
1171                                 }
1172                         }
1173                         if (rin->Dword & DNS_ZONE_REQUEST_NON_DS) {
1174                                 if (!(z->zoneinfo->Flags & DNS_RPC_ZONE_DSINTEGRATED)) {
1175                                         found = true;
1176                                 }
1177                         }
1178                         if (rin->Dword & DNS_ZONE_REQUEST_DOMAIN_DP) {
1179                                 if (z->zoneinfo->dwDpFlags & DNS_DP_DOMAIN_DEFAULT) {
1180                                         found = true;
1181                                 }
1182                         }
1183                         if (rin->Dword & DNS_ZONE_REQUEST_FOREST_DP) {
1184                                 if (z->zoneinfo->dwDpFlags & DNS_DP_FOREST_DEFAULT) {
1185                                         found = true;
1186                                 }
1187                         }
1188
1189                         if (found) {
1190                                 zlist = talloc_realloc(mem_ctx, zlist, struct dnsserver_zone *, zcount+1);
1191                                 zlist[zcount] = z;
1192                                 zcount++;
1193                         }
1194
1195                 }
1196
1197                 if (client_version == DNS_CLIENT_VERSION_W2K) {
1198                         *typeid_out = DNSSRV_TYPEID_ZONE_LIST_W2K;
1199                         rout->ZoneListW2K = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_LIST_W2K);
1200
1201                         if (zcount == 0) {
1202                                 rout->ZoneListW2K->dwZoneCount = 0;
1203                                 rout->ZoneListW2K->ZoneArray = NULL;
1204
1205                                 return WERR_OK;
1206                         }
1207
1208                         rout->ZoneListW2K->ZoneArray = talloc_zero_array(mem_ctx, struct DNS_RPC_ZONE_W2K *, zcount);
1209                         if (rout->ZoneListW2K->ZoneArray == NULL) {
1210                                 talloc_free(zlist);
1211                                 return WERR_NOMEM;
1212                         }
1213
1214                         for (i=0; i<zcount; i++) {
1215                                 rout->ZoneListW2K->ZoneArray[i] = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_W2K);
1216
1217                                 rout->ZoneListW2K->ZoneArray[i]->pszZoneName = talloc_strdup(mem_ctx, zlist[i]->name);
1218                                 rout->ZoneListW2K->ZoneArray[i]->Flags = zlist[i]->zoneinfo->Flags;
1219                                 rout->ZoneListW2K->ZoneArray[i]->ZoneType = zlist[i]->zoneinfo->dwZoneType;
1220                                 rout->ZoneListW2K->ZoneArray[i]->Version = zlist[i]->zoneinfo->Version;
1221                         }
1222                         rout->ZoneListW2K->dwZoneCount = zcount;
1223
1224                 } else {
1225                         *typeid_out = DNSSRV_TYPEID_ZONE_LIST;
1226                         rout->ZoneList = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_LIST_DOTNET);
1227
1228                         if (zcount == 0) {
1229                                 rout->ZoneList->dwRpcStructureVersion = 1;
1230                                 rout->ZoneList->dwZoneCount = 0;
1231                                 rout->ZoneList->ZoneArray = NULL;
1232
1233                                 return WERR_OK;
1234                         }
1235
1236                         rout->ZoneList->ZoneArray = talloc_zero_array(mem_ctx, struct DNS_RPC_ZONE_DOTNET *, zcount);
1237                         if (rout->ZoneList->ZoneArray == NULL) {
1238                                 talloc_free(zlist);
1239                                 return WERR_NOMEM;
1240                         }
1241
1242                         for (i=0; i<zcount; i++) {
1243                                 rout->ZoneList->ZoneArray[i] = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_DOTNET);
1244
1245                                 rout->ZoneList->ZoneArray[i]->dwRpcStructureVersion = 1;
1246                                 rout->ZoneList->ZoneArray[i]->pszZoneName = talloc_strdup(mem_ctx, zlist[i]->name);
1247                                 rout->ZoneList->ZoneArray[i]->Flags = zlist[i]->zoneinfo->Flags;
1248                                 rout->ZoneList->ZoneArray[i]->ZoneType = zlist[i]->zoneinfo->dwZoneType;
1249                                 rout->ZoneList->ZoneArray[i]->Version = zlist[i]->zoneinfo->Version;
1250                                 rout->ZoneList->ZoneArray[i]->dwDpFlags = zlist[i]->zoneinfo->dwDpFlags;
1251                                 rout->ZoneList->ZoneArray[i]->pszDpFqdn = talloc_strdup(mem_ctx, zlist[i]->zoneinfo->pszDpFqdn);
1252                         }
1253                         rout->ZoneList->dwRpcStructureVersion = 1;
1254                         rout->ZoneList->dwZoneCount = zcount;
1255                 }
1256                 talloc_free(zlist);
1257                 return WERR_OK;
1258         } else if (strcasecmp(operation, "EnumZones2") == 0) {
1259                 valid_operation = true;
1260         } else if (strcasecmp(operation, "EnumDirectoryPartitions") == 0) {
1261                 valid_operation = true;
1262         } else if (strcasecmp(operation, "DirectoryPartitionInfo") == 0) {
1263                 valid_operation = true;
1264         } else if (strcasecmp(operation, "Statistics") == 0) {
1265                 valid_operation = true;
1266         } else if (strcasecmp(operation, "IpValidate") == 0) {
1267                 valid_operation = true;
1268         }
1269
1270         if (valid_operation) {
1271                 DEBUG(0, ("dnsserver: server complex operation '%s' not implemented", operation));
1272                 return WERR_CALL_NOT_IMPLEMENTED;
1273         }
1274
1275         DEBUG(0, ("dnsserver: invalid server complex operation '%s'", operation));
1276         return WERR_DNS_ERROR_INVALID_PROPERTY;
1277 }
1278
1279 /* [MS-DNSP].pdf Section 3.1.1.2 Zone Configuration Information */
1280 static WERROR dnsserver_operate_zone(struct dnsserver_state *dsstate,
1281                                         TALLOC_CTX *mem_ctx,
1282                                         struct dnsserver_zone *z,
1283                                         unsigned int request_filter,
1284                                         const char *operation,
1285                                         const unsigned int client_version,
1286                                         enum DNS_RPC_TYPEID typeid,
1287                                         union DNSSRV_RPC_UNION *r)
1288 {
1289         bool valid_operation = false;
1290
1291         if (strcasecmp(operation, "ResetDwordProperty") == 0) {
1292                 valid_operation = true;
1293         } else if (strcasecmp(operation, "ZoneTypeReset") == 0) {
1294                 valid_operation = true;
1295         } else if (strcasecmp(operation, "PauseZone") == 0) {
1296                 valid_operation = true;
1297         } else if (strcasecmp(operation, "ResumeZone") == 0) {
1298                 valid_operation = true;
1299         } else if (strcasecmp(operation, "DeleteZone") == 0) {
1300                 valid_operation = true;
1301         } else if (strcasecmp(operation, "ReloadZone") == 0) {
1302                 valid_operation = true;
1303         } else if (strcasecmp(operation, "RefreshZone") == 0) {
1304                 valid_operation = true;
1305         } else if (strcasecmp(operation, "ExpireZone") == 0) {
1306                 valid_operation = true;
1307         } else if (strcasecmp(operation, "IncrementVersion") == 0) {
1308                 valid_operation = true;
1309         } else if (strcasecmp(operation, "WriteBackFile") == 0) {
1310                 valid_operation = true;
1311         } else if (strcasecmp(operation, "DeleteZoneFromDs") == 0) {
1312                 valid_operation = true;
1313         } else if (strcasecmp(operation, "UpdateZoneFromDs") == 0) {
1314                 valid_operation = true;
1315         } else if (strcasecmp(operation, "ZoneExport") == 0) {
1316                 valid_operation = true;
1317         } else if (strcasecmp(operation, "ZoneChangeDirectoryPartition") == 0) {
1318                 valid_operation = true;
1319         } else if (strcasecmp(operation, "DeleteNode") == 0) {
1320                 valid_operation = true;
1321         } else if (strcasecmp(operation, "DeleteRecordSet") == 0) {
1322                 valid_operation = true;
1323         } else if (strcasecmp(operation, "ForceAgingOnNode") == 0) {
1324                 valid_operation = true;
1325         } else if (strcasecmp(operation, "DatabaseFile") == 0) {
1326                 valid_operation = true;
1327         } else if (strcasecmp(operation, "MasterServers") == 0) {
1328                 valid_operation = true;
1329         } else if (strcasecmp(operation, "LocalMasterServers") == 0) {
1330                 valid_operation = true;
1331         } else if (strcasecmp(operation, "NotifyServers") == 0) {
1332                 valid_operation = true;
1333         } else if (strcasecmp(operation, "SecondaryServers") == 0) {
1334                 valid_operation = true;
1335         } else if (strcasecmp(operation, "ScavengingServers") == 0) {
1336                 valid_operation = true;
1337         } else if (strcasecmp(operation, "AllowNSRecordsAutoCreation") == 0) {
1338                 valid_operation = true;
1339         } else if (strcasecmp(operation, "BreakOnNameUpdate") == 0) {
1340                 valid_operation = true;
1341         } else if (strcasecmp(operation, "ApplicationDirectoryPartition") == 0) {
1342                 valid_operation = true;
1343         }
1344
1345         if (valid_operation) {
1346                 DEBUG(0, ("dnsserver: zone operation '%s' not implemented", operation));
1347                 return WERR_CALL_NOT_IMPLEMENTED;
1348         }
1349
1350         DEBUG(0, ("dnsserver: invalid zone operation '%s'", operation));
1351         return WERR_DNS_ERROR_INVALID_PROPERTY;
1352 }
1353
1354 static WERROR dnsserver_complex_operate_zone(struct dnsserver_state *dsstate,
1355                                         TALLOC_CTX *mem_ctx,
1356                                         struct dnsserver_zone *z,
1357                                         const char *operation,
1358                                         const unsigned int client_version,
1359                                         enum DNS_RPC_TYPEID typeid_in,
1360                                         union DNSSRV_RPC_UNION *rin,
1361                                         enum DNS_RPC_TYPEID *typeid_out,
1362                                         union DNSSRV_RPC_UNION *rout)
1363 {
1364         if (strcasecmp(operation, "QueryDwordProperty") == 0) {
1365                 if (typeid_in == DNSSRV_TYPEID_LPSTR) {
1366                         return dnsserver_query_zone(dsstate, mem_ctx, z,
1367                                                 rin->String,
1368                                                 client_version,
1369                                                 typeid_out,
1370                                                 rout);
1371
1372                 }
1373         }
1374
1375         DEBUG(0,("dnsserver: Invalid zone operation %s", operation));
1376         return WERR_DNS_ERROR_INVALID_PROPERTY;
1377 }
1378
1379 /* dnsserver enumerate function */
1380
1381 static WERROR dnsserver_enumerate_root_records(struct dnsserver_state *dsstate,
1382                                         TALLOC_CTX *mem_ctx,
1383                                         unsigned int client_version,
1384                                         const char *node_name,
1385                                         enum dns_record_type record_type,
1386                                         unsigned int select_flag,
1387                                         unsigned int *buffer_length,
1388                                         struct DNS_RPC_RECORDS_ARRAY **buffer)
1389 {
1390         TALLOC_CTX *tmp_ctx;
1391         const char * const attrs[] = { "name", "dnsRecord", NULL };
1392         struct ldb_result *res;
1393         struct ldb_dn *dn;
1394         struct DNS_RPC_RECORDS_ARRAY *recs;
1395         char **add_names;
1396         char *rname;
1397         int add_count;
1398         int i, ret, len;
1399         WERROR status;
1400
1401         tmp_ctx = talloc_new(mem_ctx);
1402         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1403
1404         dn = ldb_dn_copy(tmp_ctx, ldb_get_default_basedn(dsstate->samdb));
1405         W_ERROR_HAVE_NO_MEMORY_AND_FREE(dn, tmp_ctx);
1406
1407         if (!ldb_dn_add_child_fmt(dn, "DC=RootDNSServers,CN=MicrosoftDNS,DC=DomainDnsZones")) {
1408                 talloc_free(tmp_ctx);
1409                 return WERR_NOMEM;
1410         }
1411
1412         ret = ldb_search(dsstate->samdb, tmp_ctx, &res, dn,
1413                                 LDB_SCOPE_ONELEVEL, attrs, "(&(objectClass=dnsNode)(name=@))");
1414         if (ret != LDB_SUCCESS) {
1415                 talloc_free(tmp_ctx);
1416                 return WERR_INTERNAL_DB_ERROR;
1417         }
1418         if (res->count == 0) {
1419                 talloc_free(tmp_ctx);
1420                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1421         }
1422
1423         recs = talloc_zero(mem_ctx, struct DNS_RPC_RECORDS_ARRAY);
1424         W_ERROR_HAVE_NO_MEMORY_AND_FREE(recs, tmp_ctx);
1425
1426         add_names = NULL;
1427         add_count = 0;
1428
1429         for (i=0; i<res->count; i++) {
1430                 status = dns_fill_records_array(tmp_ctx, NULL, record_type,
1431                                                 select_flag, NULL,
1432                                                 res->msgs[i], recs,
1433                                                 &add_names, &add_count);
1434                 if (!W_ERROR_IS_OK(status)) {
1435                         talloc_free(tmp_ctx);
1436                         return status;
1437                 }
1438         }
1439         talloc_free(res);
1440
1441         /* Add any additional records */
1442         if (select_flag & DNS_RPC_VIEW_ADDITIONAL_DATA) {
1443                 for (i=0; i<add_count; i++) {
1444                         ret = ldb_search(dsstate->samdb, tmp_ctx, &res, dn,
1445                                         LDB_SCOPE_ONELEVEL, attrs,
1446                                         "(&(objectClass=dnsNode)(name=%s))", add_names[i]);
1447                         if (ret != LDB_SUCCESS || res->count == 0) {
1448                                 talloc_free(res);
1449                                 continue;
1450                         }
1451
1452                         len = strlen(add_names[i]);
1453                         if (add_names[i][len-1] == '.') {
1454                                 rname = talloc_strdup(tmp_ctx, add_names[i]);
1455                         } else {
1456                                 rname = talloc_asprintf(tmp_ctx, "%s.", add_names[i]);
1457                         }
1458                         status = dns_fill_records_array(tmp_ctx, NULL, DNS_TYPE_A,
1459                                                         select_flag, rname,
1460                                                         res->msgs[0], recs,
1461                                                         NULL, NULL);
1462                         talloc_free(rname);
1463                         talloc_free(res);
1464                 }
1465         }
1466
1467         talloc_free(tmp_ctx);
1468
1469         *buffer_length = ndr_size_DNS_RPC_RECORDS_ARRAY(recs, 0);
1470         *buffer = recs;
1471
1472         return WERR_OK;
1473 }
1474
1475
1476 static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate,
1477                                         TALLOC_CTX *mem_ctx,
1478                                         struct dnsserver_zone *z,
1479                                         unsigned int client_version,
1480                                         const char *node_name,
1481                                         const char *start_child,
1482                                         enum dns_record_type record_type,
1483                                         unsigned int select_flag,
1484                                         const char *filter_start,
1485                                         const char *filter_stop,
1486                                         unsigned int *buffer_length,
1487                                         struct DNS_RPC_RECORDS_ARRAY **buffer)
1488 {
1489         TALLOC_CTX *tmp_ctx;
1490         char *name, *branch_name;
1491         const char * const attrs[] = { "name", "dnsRecord", NULL };
1492         struct ldb_result *res;
1493         struct DNS_RPC_RECORDS_ARRAY *recs;
1494         char **add_names = NULL;
1495         const char *ptr;
1496         char *rname;
1497         int add_count = 0;
1498         int i, ret, len;
1499         WERROR status;
1500
1501         tmp_ctx = talloc_new(mem_ctx);
1502         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1503
1504         name = dns_split_node_name(tmp_ctx, node_name, z->name);
1505         W_ERROR_HAVE_NO_MEMORY_AND_FREE(name, tmp_ctx);
1506
1507         /* search all records under parent tree */
1508         if (strcmp(name, z->name) == 0) {
1509                 ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z->zone_dn,
1510                                 LDB_SCOPE_ONELEVEL, attrs, "(objectClass=dnsNode)");
1511         } else {
1512                 ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z->zone_dn,
1513                                 LDB_SCOPE_ONELEVEL, attrs,
1514                                 "(&(objectClass=dnsNode)(|(name=%s)(name=*.%s)))",
1515                                 name, name);
1516         }
1517         if (ret != LDB_SUCCESS) {
1518                 talloc_free(tmp_ctx);
1519                 return WERR_INTERNAL_DB_ERROR;
1520         }
1521         if (res->count == 0) {
1522                 talloc_free(tmp_ctx);
1523                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1524         }
1525
1526         recs = talloc_zero(mem_ctx, struct DNS_RPC_RECORDS_ARRAY);
1527         W_ERROR_HAVE_NO_MEMORY_AND_FREE(recs, tmp_ctx);
1528
1529         /* Sort the names, so that the first record is the parent record */
1530         ldb_qsort(res->msgs, res->count, sizeof(struct ldb_message *), name,
1531                         (ldb_qsort_cmp_fn_t)dns_name_compare);
1532
1533         /* Add the parent record with blank name */
1534         ptr = ldb_msg_find_attr_as_string(res->msgs[0], "name", NULL);
1535         if (strcmp(ptr, name) == 0 || strcmp(ptr, "@") == 0) {
1536                 /* parent record found */
1537                 if (select_flag & DNS_RPC_VIEW_ONLY_CHILDREN) {
1538                         status = WERR_OK;
1539                 } else {
1540                         status = dns_fill_records_array(tmp_ctx, z, record_type,
1541                                                         select_flag, NULL,
1542                                                         res->msgs[0], recs,
1543                                                         &add_names, &add_count);
1544                 }
1545                 i = 1;
1546         } else {
1547                 /* parent record not in the search */
1548                 if (select_flag & DNS_RPC_VIEW_ONLY_CHILDREN) {
1549                         status = WERR_OK;
1550                 } else {
1551                         status = dns_fill_records_array(tmp_ctx, z, record_type,
1552                                                         select_flag, NULL,
1553                                                         NULL, recs,
1554                                                         &add_names, &add_count);
1555                 }
1556                 i = 0;
1557         }
1558
1559         if (!W_ERROR_IS_OK(status)) {
1560                 talloc_free(tmp_ctx);
1561                 return status;
1562         }
1563
1564         /* Add all the children records */
1565         if (!(select_flag & DNS_RPC_VIEW_NO_CHILDREN)) {
1566                 for ( ; i<res->count; i++) {
1567                         char *name2;
1568                         const char *tmp_str;
1569
1570                         ptr = ldb_msg_find_attr_as_string(res->msgs[i], "name", NULL);
1571                         name2 = dns_split_node_name(tmp_ctx, ptr, name);
1572                         tmp_str = strrchr(name2, '.');
1573                         if (tmp_str == NULL) {
1574                                 branch_name = talloc_strdup(tmp_ctx, name2);
1575                         } else {
1576                                 /* Skip '.' */
1577                                 branch_name = talloc_strdup(tmp_ctx, &tmp_str[1]);
1578                         }
1579                         talloc_free(name2);
1580
1581                         status = dns_fill_records_array(tmp_ctx, z, record_type,
1582                                                         select_flag, branch_name,
1583                                                         res->msgs[i], recs,
1584                                                         &add_names, &add_count);
1585                         if (!W_ERROR_IS_OK(status)) {
1586                                 talloc_free(tmp_ctx);
1587                                 return status;
1588                         }
1589
1590                         talloc_free(branch_name);
1591                 }
1592         }
1593         talloc_free(res);
1594
1595         talloc_free(name);
1596
1597         /* Add any additional records */
1598         if (select_flag & DNS_RPC_VIEW_ADDITIONAL_DATA) {
1599                 for (i=0; i<add_count; i++) {
1600                         name = dns_split_node_name(tmp_ctx, add_names[i], z->name);
1601                         ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z->zone_dn,
1602                                         LDB_SCOPE_ONELEVEL, attrs,
1603                                         "(&(objectClass=dnsNode)(name=%s))", name);
1604                         talloc_free(name);
1605                         if (ret != LDB_SUCCESS || res->count == 0) {
1606                                 talloc_free(res);
1607                                 continue;
1608                         }
1609
1610                         len = strlen(add_names[i]);
1611                         if (add_names[i][len-1] == '.') {
1612                                 rname = talloc_strdup(tmp_ctx, add_names[i]);
1613                         } else {
1614                                 rname = talloc_asprintf(tmp_ctx, "%s.", add_names[i]);
1615                         }
1616                         status = dns_fill_records_array(tmp_ctx, NULL, DNS_TYPE_A,
1617                                                         select_flag, rname,
1618                                                         res->msgs[0], recs,
1619                                                         NULL, NULL);
1620                         talloc_free(rname);
1621                         talloc_free(res);
1622                 }
1623         }
1624
1625         *buffer_length = ndr_size_DNS_RPC_RECORDS_ARRAY(recs, 0);
1626         *buffer = recs;
1627
1628         return WERR_OK;
1629 }
1630
1631 /* dnsserver update function */
1632
1633 static WERROR dnsserver_update_record(struct dnsserver_state *dsstate,
1634                                         TALLOC_CTX *mem_ctx,
1635                                         struct dnsserver_zone *z,
1636                                         unsigned int client_version,
1637                                         const char *node_name,
1638                                         struct DNS_RPC_RECORD_BUF *add_buf,
1639                                         struct DNS_RPC_RECORD_BUF *del_buf)
1640 {
1641         TALLOC_CTX *tmp_ctx;
1642         char *name;
1643         WERROR status;
1644
1645         tmp_ctx = talloc_new(mem_ctx);
1646         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1647
1648         name = dns_split_node_name(tmp_ctx, node_name, z->name);
1649         W_ERROR_HAVE_NO_MEMORY_AND_FREE(name, tmp_ctx);
1650
1651         if (add_buf != NULL) {
1652                 if (del_buf == NULL) {
1653                         /* Add record */
1654                         status = dnsserver_db_add_record(tmp_ctx, dsstate->samdb,
1655                                                                 z, name,
1656                                                                 &add_buf->rec);
1657                 } else {
1658                         /* Update record */
1659                         status = dnsserver_db_update_record(tmp_ctx, dsstate->samdb,
1660                                                                 z, name,
1661                                                                 &add_buf->rec,
1662                                                                 &del_buf->rec);
1663                 }
1664         } else {
1665                 if (del_buf == NULL) {
1666                         /* Add empty node */
1667                         status = dnsserver_db_add_empty_node(tmp_ctx, dsstate->samdb,
1668                                                                 z, name);
1669                 } else {
1670                         /* Delete record */
1671                         status = dnsserver_db_delete_record(tmp_ctx, dsstate->samdb,
1672                                                                 z, name,
1673                                                                 &del_buf->rec);
1674                 }
1675         }
1676
1677         talloc_free(tmp_ctx);
1678         return status;
1679 }
1680
1681
1682 /* dnsserver interface functions */
1683
1684 static WERROR dcesrv_DnssrvOperation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvOperation *r)
1685 {
1686         struct dnsserver_state *dsstate;
1687         struct dnsserver_zone *z = NULL;
1688         uint32_t request_filter = 0;
1689         WERROR ret;
1690
1691         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1692                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1693         }
1694
1695         if (r->in.dwContext == 0) {
1696                 if (r->in.pszZone != NULL) {
1697                         request_filter = dnsserver_zone_to_request_filter(r->in.pszZone);
1698                 }
1699         } else {
1700                 request_filter = r->in.dwContext;
1701         }
1702
1703         if (r->in.pszZone == NULL) {
1704                 ret = dnsserver_operate_server(dsstate, mem_ctx,
1705                                                 r->in.pszOperation,
1706                                                 DNS_CLIENT_VERSION_W2K,
1707                                                 r->in.dwTypeId,
1708                                                 &r->in.pData);
1709         } else {
1710                 ret = dnsserver_operate_zone(dsstate, mem_ctx, z,
1711                                                 request_filter,
1712                                                 r->in.pszOperation,
1713                                                 DNS_CLIENT_VERSION_W2K,
1714                                                 r->in.dwTypeId,
1715                                                 &r->in.pData);
1716         }
1717
1718         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1719                 NDR_PRINT_FUNCTION_DEBUG(DnssrvOperation, NDR_IN, r);
1720         }
1721         return ret;
1722 }
1723
1724 static WERROR dcesrv_DnssrvQuery(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvQuery *r)
1725 {
1726         struct dnsserver_state *dsstate;
1727         struct dnsserver_zone *z;
1728         WERROR ret;
1729
1730         ZERO_STRUCTP(r->out.pdwTypeId);
1731         ZERO_STRUCTP(r->out.ppData);
1732
1733         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1734                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1735         }
1736
1737         if (r->in.pszZone == NULL) {
1738                 /* FIXME: DNS Server Configuration Access Control List */
1739                 ret = dnsserver_query_server(dsstate, mem_ctx,
1740                                                 r->in.pszOperation,
1741                                                 DNS_CLIENT_VERSION_W2K,
1742                                                 r->out.pdwTypeId,
1743                                                 r->out.ppData);
1744         } else {
1745                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
1746                 if (z == NULL) {
1747                         return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
1748                 }
1749
1750                 ret = dnsserver_query_zone(dsstate, mem_ctx, z,
1751                                                 r->in.pszOperation,
1752                                                 DNS_CLIENT_VERSION_W2K,
1753                                                 r->out.pdwTypeId,
1754                                                 r->out.ppData);
1755         }
1756
1757         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1758                 NDR_PRINT_FUNCTION_DEBUG(DnssrvQuery, NDR_IN, r);
1759         }
1760         return ret;
1761 }
1762
1763 static WERROR dcesrv_DnssrvComplexOperation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvComplexOperation *r)
1764 {
1765         struct dnsserver_state *dsstate;
1766         struct dnsserver_zone *z;
1767         WERROR ret;
1768
1769         ZERO_STRUCTP(r->out.pdwTypeOut);
1770         ZERO_STRUCTP(r->out.ppDataOut);
1771
1772         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1773                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1774         }
1775
1776         if (r->in.pszZone == NULL) {
1777                 /* Server operation */
1778                 ret = dnsserver_complex_operate_server(dsstate, mem_ctx,
1779                                                         r->in.pszOperation,
1780                                                         DNS_CLIENT_VERSION_W2K,
1781                                                         r->in.dwTypeIn,
1782                                                         &r->in.pDataIn,
1783                                                         r->out.pdwTypeOut,
1784                                                         r->out.ppDataOut);
1785         } else {
1786                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
1787                 if (z == NULL) {
1788                         return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
1789                 }
1790
1791                 ret = dnsserver_complex_operate_zone(dsstate, mem_ctx, z,
1792                                                         r->in.pszOperation,
1793                                                         DNS_CLIENT_VERSION_W2K,
1794                                                         r->in.dwTypeIn,
1795                                                         &r->in.pDataIn,
1796                                                         r->out.pdwTypeOut,
1797                                                         r->out.ppDataOut);
1798         }
1799
1800         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1801                 NDR_PRINT_FUNCTION_DEBUG(DnssrvComplexOperation, NDR_IN, r);
1802         }
1803         return ret;
1804 }
1805
1806 static WERROR dcesrv_DnssrvEnumRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvEnumRecords *r)
1807 {
1808         struct dnsserver_state *dsstate;
1809         struct dnsserver_zone *z;
1810         WERROR ret;
1811
1812         ZERO_STRUCTP(r->out.pdwBufferLength);
1813         ZERO_STRUCTP(r->out.pBuffer);
1814
1815         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1816                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1817         }
1818
1819         if (r->in.pszZone == NULL) {
1820                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1821         }
1822
1823         if (strcasecmp(r->in.pszZone, "..RootHints") == 0) {
1824                 ret = dnsserver_enumerate_root_records(dsstate, mem_ctx,
1825                                         DNS_CLIENT_VERSION_W2K,
1826                                         r->in.pszNodeName,
1827                                         r->in.wRecordType,
1828                                         r->in.fSelectFlag,
1829                                         r->out.pdwBufferLength,
1830                                         r->out.pBuffer);
1831         } else {
1832                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
1833                 if (z == NULL) {
1834                         return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1835                 }
1836
1837                 ret = dnsserver_enumerate_records(dsstate, mem_ctx, z,
1838                                         DNS_CLIENT_VERSION_W2K,
1839                                         r->in.pszNodeName,
1840                                         r->in.pszStartChild,
1841                                         r->in.wRecordType,
1842                                         r->in.fSelectFlag,
1843                                         r->in.pszFilterStart,
1844                                         r->in.pszFilterStop,
1845                                         r->out.pdwBufferLength,
1846                                         r->out.pBuffer);
1847         }
1848
1849         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1850                 NDR_PRINT_FUNCTION_DEBUG(DnssrvEnumRecords, NDR_IN, r);
1851         }
1852         return ret;
1853 }
1854
1855 static WERROR dcesrv_DnssrvUpdateRecord(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvUpdateRecord *r)
1856 {
1857         struct dnsserver_state *dsstate;
1858         struct dnsserver_zone *z;
1859         WERROR ret;
1860
1861         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1862                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1863         }
1864
1865         if (r->in.pszZone == NULL) {
1866                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1867         }
1868
1869         z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
1870         if (z == NULL) {
1871                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1872         }
1873
1874         ret = dnsserver_update_record(dsstate, mem_ctx, z,
1875                                         DNS_CLIENT_VERSION_W2K,
1876                                         r->in.pszNodeName,
1877                                         r->in.pAddRecord,
1878                                         r->in.pDeleteRecord);
1879
1880         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1881                 NDR_PRINT_FUNCTION_DEBUG(DnssrvUpdateRecord, NDR_IN, r);
1882         }
1883         return ret;
1884 }
1885
1886 static WERROR dcesrv_DnssrvOperation2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvOperation2 *r)
1887 {
1888         struct dnsserver_state *dsstate;
1889         struct dnsserver_zone *z = NULL;
1890         uint32_t request_filter = 0;
1891         WERROR ret;
1892
1893         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1894                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1895         }
1896
1897         if (r->in.dwContext == 0) {
1898                 if (r->in.pszZone != NULL) {
1899                         request_filter = dnsserver_zone_to_request_filter(r->in.pszZone);
1900                 }
1901         } else {
1902                 request_filter = r->in.dwContext;
1903         }
1904
1905         if (r->in.pszZone == NULL) {
1906                 ret = dnsserver_operate_server(dsstate, mem_ctx,
1907                                                 r->in.pszOperation,
1908                                                 r->in.dwClientVersion,
1909                                                 r->in.dwTypeId,
1910                                                 &r->in.pData);
1911         } else {
1912                 ret = dnsserver_operate_zone(dsstate, mem_ctx, z,
1913                                                 request_filter,
1914                                                 r->in.pszOperation,
1915                                                 r->in.dwClientVersion,
1916                                                 r->in.dwTypeId,
1917                                                 &r->in.pData);
1918         }
1919
1920         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1921                 NDR_PRINT_FUNCTION_DEBUG(DnssrvOperation2, NDR_IN, r);
1922         }
1923         return ret;
1924 }
1925
1926 static WERROR dcesrv_DnssrvQuery2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvQuery2 *r)
1927 {
1928         struct dnsserver_state *dsstate;
1929         struct dnsserver_zone *z;
1930         WERROR ret;
1931
1932         ZERO_STRUCTP(r->out.pdwTypeId);
1933         ZERO_STRUCTP(r->out.ppData);
1934
1935         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1936                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1937         }
1938
1939         if (r->in.pszZone == NULL) {
1940                 /* FIXME: DNS Server Configuration Access Control List */
1941                 ret = dnsserver_query_server(dsstate, mem_ctx,
1942                                                 r->in.pszOperation,
1943                                                 r->in.dwClientVersion,
1944                                                 r->out.pdwTypeId,
1945                                                 r->out.ppData);
1946         } else {
1947                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
1948                 if (z == NULL) {
1949                         return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
1950                 }
1951
1952                 ret = dnsserver_query_zone(dsstate, mem_ctx, z,
1953                                         r->in.pszOperation,
1954                                         r->in.dwClientVersion,
1955                                         r->out.pdwTypeId,
1956                                         r->out.ppData);
1957         }
1958
1959         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1960                 NDR_PRINT_FUNCTION_DEBUG(DnssrvQuery2, NDR_IN, r);
1961         }
1962         return ret;
1963 }
1964
1965 static WERROR dcesrv_DnssrvComplexOperation2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvComplexOperation2 *r)
1966 {
1967         struct dnsserver_state *dsstate;
1968         struct dnsserver_zone *z;
1969         WERROR ret;
1970
1971         ZERO_STRUCTP(r->out.pdwTypeOut);
1972         ZERO_STRUCTP(r->out.ppDataOut);
1973
1974         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1975                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1976         }
1977
1978         if (r->in.pszZone == NULL) {
1979                 /* Server operation */
1980                 ret =  dnsserver_complex_operate_server(dsstate, mem_ctx,
1981                                                         r->in.pszOperation,
1982                                                         r->in.dwClientVersion,
1983                                                         r->in.dwTypeIn,
1984                                                         &r->in.pDataIn,
1985                                                         r->out.pdwTypeOut,
1986                                                         r->out.ppDataOut);
1987         } else {
1988
1989                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
1990                 if (z == NULL) {
1991                         return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
1992                 }
1993
1994                 ret = dnsserver_complex_operate_zone(dsstate, mem_ctx, z,
1995                                                         r->in.pszOperation,
1996                                                         r->in.dwClientVersion,
1997                                                         r->in.dwTypeIn,
1998                                                         &r->in.pDataIn,
1999                                                         r->out.pdwTypeOut,
2000                                                         r->out.ppDataOut);
2001         }
2002
2003         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2004                 NDR_PRINT_FUNCTION_DEBUG(DnssrvComplexOperation2, NDR_IN, r);
2005         }
2006         return ret;
2007 }
2008
2009 static WERROR dcesrv_DnssrvEnumRecords2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvEnumRecords2 *r)
2010 {
2011         struct dnsserver_state *dsstate;
2012         struct dnsserver_zone *z;
2013         WERROR ret;
2014
2015         ZERO_STRUCTP(r->out.pdwBufferLength);
2016         ZERO_STRUCTP(r->out.pBuffer);
2017
2018         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
2019                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
2020         }
2021
2022         if (r->in.pszZone == NULL) {
2023                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2024         }
2025
2026         if (strcasecmp(r->in.pszZone, "..RootHints") == 0) {
2027                 ret =  dnsserver_enumerate_root_records(dsstate, mem_ctx,
2028                                         r->in.dwClientVersion,
2029                                         r->in.pszNodeName,
2030                                         r->in.wRecordType,
2031                                         r->in.fSelectFlag,
2032                                         r->out.pdwBufferLength,
2033                                         r->out.pBuffer);
2034         } else {
2035                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
2036                 if (z == NULL) {
2037                         return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2038                 }
2039
2040                 ret =  dnsserver_enumerate_records(dsstate, mem_ctx, z,
2041                                         r->in.dwClientVersion,
2042                                         r->in.pszNodeName,
2043                                         r->in.pszStartChild,
2044                                         r->in.wRecordType,
2045                                         r->in.fSelectFlag,
2046                                         r->in.pszFilterStart,
2047                                         r->in.pszFilterStop,
2048                                         r->out.pdwBufferLength,
2049                                         r->out.pBuffer);
2050
2051         }
2052
2053         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2054                 NDR_PRINT_FUNCTION_DEBUG(DnssrvEnumRecords2, NDR_IN, r);
2055         }
2056         return ret;
2057 }
2058
2059 static WERROR dcesrv_DnssrvUpdateRecord2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvUpdateRecord2 *r)
2060 {
2061         struct dnsserver_state *dsstate;
2062         struct dnsserver_zone *z;
2063         WERROR ret;
2064
2065         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
2066                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
2067         }
2068
2069         if (r->in.pszZone == NULL) {
2070                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2071         }
2072
2073         z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
2074         if (z == NULL) {
2075                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2076         }
2077
2078         ret = dnsserver_update_record(dsstate, mem_ctx, z,
2079                                         r->in.dwClientVersion,
2080                                         r->in.pszNodeName,
2081                                         r->in.pAddRecord,
2082                                         r->in.pDeleteRecord);
2083
2084         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2085                 NDR_PRINT_FUNCTION_DEBUG(DnssrvUpdateRecord2, NDR_IN, r);
2086         }
2087         return ret;
2088 }
2089
2090 /* include the generated boilerplate */
2091 #include "librpc/gen_ndr/ndr_dnsserver_s.c"