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