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