s4/rpc_server/dnsserver: clang: fix Value stored to 'status' is never read
[timbeale/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(context, iface) \
32         dcesrv_interface_dnsserver_bind(context, iface)
33 static NTSTATUS dcesrv_interface_dnsserver_bind(struct dcesrv_connection_context *context,
34                                                 const struct dcesrv_interface *iface)
35 {
36         return dcesrv_interface_bind_require_integrity(context, iface);
37 }
38
39 #define DNSSERVER_STATE_MAGIC 0xc9657ab4
40 struct dnsserver_state {
41         struct loadparm_context *lp_ctx;
42         struct ldb_context *samdb;
43         struct dnsserver_partition *partitions;
44         struct dnsserver_zone *zones;
45         int zones_count;
46         struct dnsserver_serverinfo *serverinfo;
47 };
48
49
50 /* Utility functions */
51
52 static void dnsserver_reload_zones(struct dnsserver_state *dsstate)
53 {
54         struct dnsserver_partition *p;
55         struct dnsserver_zone *zones, *z, *znext, *zmatch;
56         struct dnsserver_zone *old_list, *new_list;
57
58         old_list = dsstate->zones;
59         new_list = NULL;
60
61         for (p = dsstate->partitions; p; p = p->next) {
62                 zones = dnsserver_db_enumerate_zones(dsstate, dsstate->samdb, p);
63                 if (zones == NULL) {
64                         continue;
65                 }
66                 for (z = zones; z; ) {
67                         znext = z->next;
68                         zmatch = dnsserver_find_zone(old_list, z->name);
69                         if (zmatch == NULL) {
70                                 /* Missing zone */
71                                 z->zoneinfo = dnsserver_init_zoneinfo(z, dsstate->serverinfo);
72                                 if (z->zoneinfo == NULL) {
73                                         continue;
74                                 }
75                                 DLIST_ADD_END(new_list, z);
76                                 p->zones_count++;
77                                 dsstate->zones_count++;
78                         } else {
79                                 /* Existing zone */
80                                 talloc_free(z);
81                                 DLIST_REMOVE(old_list, zmatch);
82                                 DLIST_ADD_END(new_list, zmatch);
83                         }
84                         z = znext;
85                 }
86         }
87
88         if (new_list == NULL) {
89                 return;
90         }
91
92         /* Deleted zones */
93         for (z = old_list; z; ) {
94                 znext = z->next;
95                 z->partition->zones_count--;
96                 dsstate->zones_count--;
97                 talloc_free(z);
98                 z = znext;
99         }
100
101         dsstate->zones = new_list;
102 }
103
104
105 static struct dnsserver_state *dnsserver_connect(struct dcesrv_call_state *dce_call)
106 {
107         struct auth_session_info *session_info =
108                 dcesrv_call_session_info(dce_call);
109         struct dnsserver_state *dsstate;
110         struct dnsserver_zone *zones, *z, *znext;
111         struct dnsserver_partition *partitions, *p;
112         NTSTATUS status;
113
114         dsstate = dcesrv_iface_state_find_conn(dce_call,
115                                                DNSSERVER_STATE_MAGIC,
116                                                struct dnsserver_state);
117         if (dsstate != NULL) {
118                 return dsstate;
119         }
120
121         dsstate = talloc_zero(dce_call, struct dnsserver_state);
122         if (dsstate == NULL) {
123                 return NULL;
124         }
125
126         dsstate->lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
127
128         /* FIXME: create correct auth_session_info for connecting user */
129         dsstate->samdb = samdb_connect(dsstate,
130                                        dce_call->event_ctx,
131                                        dsstate->lp_ctx,
132                                        session_info,
133                                        dce_call->conn->remote_address,
134                                        0);
135         if (dsstate->samdb == NULL) {
136                 DEBUG(0,("dnsserver: Failed to open samdb"));
137                 goto failed;
138         }
139
140         /* Initialize server info */
141         dsstate->serverinfo = dnsserver_init_serverinfo(dsstate,
142                                                         dsstate->lp_ctx,
143                                                         dsstate->samdb);
144         if (dsstate->serverinfo == NULL) {
145                 goto failed;
146         }
147
148         /* Search for DNS partitions */
149         partitions = dnsserver_db_enumerate_partitions(dsstate, dsstate->serverinfo, dsstate->samdb);
150         if (partitions == NULL) {
151                 goto failed;
152         }
153         dsstate->partitions = partitions;
154
155         /* Search for DNS zones */
156         for (p = partitions; p; p = p->next) {
157                 zones = dnsserver_db_enumerate_zones(dsstate, dsstate->samdb, p);
158                 if (zones == NULL) {
159                         goto failed;
160                 }
161                 for (z = zones; z; ) {
162                         znext = z->next;
163                         if (dnsserver_find_zone(dsstate->zones, z->name) == NULL) {
164                                 z->zoneinfo = dnsserver_init_zoneinfo(z, dsstate->serverinfo);
165                                 if (z->zoneinfo == NULL) {
166                                         goto failed;
167                                 }
168                                 DLIST_ADD_END(dsstate->zones, z);
169                                 p->zones_count++;
170                                 dsstate->zones_count++;
171                         } else {
172                                 /* Ignore duplicate zone */
173                                 DEBUG(3,("dnsserver: Ignoring duplicate zone '%s' from '%s'",
174                                          z->name, ldb_dn_get_linearized(z->zone_dn)));
175                         }
176                         z = znext;
177                 }
178         }
179
180         status = dcesrv_iface_state_store_conn(dce_call,
181                                                DNSSERVER_STATE_MAGIC,
182                                                dsstate);
183         if (!NT_STATUS_IS_OK(status)) {
184                 goto failed;
185         }
186
187         return dsstate;
188
189 failed:
190         talloc_free(dsstate);
191         dsstate = NULL;
192         return NULL;
193 }
194
195
196 /* dnsserver query functions */
197
198 /* [MS-DNSP].pdf Section 3.1.1.1 DNS Server Configuration Information */
199 static WERROR dnsserver_query_server(struct dnsserver_state *dsstate,
200                                         TALLOC_CTX *mem_ctx,
201                                         const char *operation,
202                                         const unsigned int client_version,
203                                         enum DNS_RPC_TYPEID *typeid,
204                                         union DNSSRV_RPC_UNION *r)
205 {
206         uint8_t is_integer, is_addresses, is_string, is_wstring, is_stringlist;
207         uint32_t answer_integer;
208         struct IP4_ARRAY *answer_iparray;
209         struct DNS_ADDR_ARRAY *answer_addrarray;
210         char *answer_string;
211         struct DNS_RPC_UTF8_STRING_LIST *answer_stringlist;
212         struct dnsserver_serverinfo *serverinfo;
213
214         serverinfo = dsstate->serverinfo;
215
216         if (strcasecmp(operation, "ServerInfo") == 0) {
217                 if (client_version == DNS_CLIENT_VERSION_W2K) {
218                         *typeid = DNSSRV_TYPEID_SERVER_INFO_W2K;
219                         r->ServerInfoW2K = talloc_zero(mem_ctx, struct DNS_RPC_SERVER_INFO_W2K);
220
221                         r->ServerInfoW2K->dwVersion = serverinfo->dwVersion;
222                         r->ServerInfoW2K->fBootMethod = serverinfo->fBootMethod;
223                         r->ServerInfoW2K->fAdminConfigured = serverinfo->fAdminConfigured;
224                         r->ServerInfoW2K->fAllowUpdate = serverinfo->fAllowUpdate;
225                         r->ServerInfoW2K->fDsAvailable = serverinfo->fDsAvailable;
226                         r->ServerInfoW2K->pszServerName = talloc_strdup(mem_ctx, serverinfo->pszServerName);
227                         r->ServerInfoW2K->pszDsContainer = talloc_strdup(mem_ctx, serverinfo->pszDsContainer);
228                         r->ServerInfoW2K->aipServerAddrs = dns_addr_array_to_ip4_array(mem_ctx,
229                                                                                        serverinfo->aipServerAddrs);
230                         r->ServerInfoW2K->aipListenAddrs = dns_addr_array_to_ip4_array(mem_ctx,
231                                                                                        serverinfo->aipListenAddrs);
232                         r->ServerInfoW2K->aipForwarders = ip4_array_copy(mem_ctx, serverinfo->aipForwarders);
233                         r->ServerInfoW2K->dwLogLevel = serverinfo->dwLogLevel;
234                         r->ServerInfoW2K->dwDebugLevel = serverinfo->dwDebugLevel;
235                         r->ServerInfoW2K->dwForwardTimeout = serverinfo->dwForwardTimeout;
236                         r->ServerInfoW2K->dwRpcProtocol = serverinfo->dwRpcProtocol;
237                         r->ServerInfoW2K->dwNameCheckFlag = serverinfo->dwNameCheckFlag;
238                         r->ServerInfoW2K->cAddressAnswerLimit = serverinfo->cAddressAnswerLimit;
239                         r->ServerInfoW2K->dwRecursionRetry = serverinfo->dwRecursionRetry;
240                         r->ServerInfoW2K->dwRecursionTimeout = serverinfo->dwRecursionTimeout;
241                         r->ServerInfoW2K->dwMaxCacheTtl = serverinfo->dwMaxCacheTtl;
242                         r->ServerInfoW2K->dwDsPollingInterval = serverinfo->dwDsPollingInterval;
243                         r->ServerInfoW2K->dwScavengingInterval = serverinfo->dwScavengingInterval;
244                         r->ServerInfoW2K->dwDefaultRefreshInterval = serverinfo->dwDefaultRefreshInterval;
245                         r->ServerInfoW2K->dwDefaultNoRefreshInterval = serverinfo->dwDefaultNoRefreshInterval;
246                         r->ServerInfoW2K->fAutoReverseZones = serverinfo->fAutoReverseZones;
247                         r->ServerInfoW2K->fAutoCacheUpdate = serverinfo->fAutoCacheUpdate;
248                         r->ServerInfoW2K->fRecurseAfterForwarding = serverinfo->fRecurseAfterForwarding;
249                         r->ServerInfoW2K->fForwardDelegations = serverinfo->fForwardDelegations;
250                         r->ServerInfoW2K->fNoRecursion = serverinfo->fNoRecursion;
251                         r->ServerInfoW2K->fSecureResponses = serverinfo->fSecureResponses;
252                         r->ServerInfoW2K->fRoundRobin = serverinfo->fRoundRobin;
253                         r->ServerInfoW2K->fLocalNetPriority = serverinfo->fLocalNetPriority;
254                         r->ServerInfoW2K->fBindSecondaries = serverinfo->fBindSecondaries;
255                         r->ServerInfoW2K->fWriteAuthorityNs = serverinfo->fWriteAuthorityNs;
256                         r->ServerInfoW2K->fStrictFileParsing = serverinfo->fStrictFileParsing;
257                         r->ServerInfoW2K->fLooseWildcarding = serverinfo->fLooseWildcarding;
258                         r->ServerInfoW2K->fDefaultAgingState = serverinfo->fDefaultAgingState;
259
260                 } else if (client_version == DNS_CLIENT_VERSION_DOTNET) {
261                         *typeid = DNSSRV_TYPEID_SERVER_INFO_DOTNET;
262                         r->ServerInfoDotNet = talloc_zero(mem_ctx, struct DNS_RPC_SERVER_INFO_DOTNET);
263
264                         r->ServerInfoDotNet->dwRpcStructureVersion = 0x01;
265                         r->ServerInfoDotNet->dwVersion = serverinfo->dwVersion;
266                         r->ServerInfoDotNet->fBootMethod = serverinfo->fBootMethod;
267                         r->ServerInfoDotNet->fAdminConfigured = serverinfo->fAdminConfigured;
268                         r->ServerInfoDotNet->fAllowUpdate = serverinfo->fAllowUpdate;
269                         r->ServerInfoDotNet->fDsAvailable = serverinfo->fDsAvailable;
270                         r->ServerInfoDotNet->pszServerName = talloc_strdup(mem_ctx, serverinfo->pszServerName);
271                         r->ServerInfoDotNet->pszDsContainer = talloc_strdup(mem_ctx, serverinfo->pszDsContainer);
272                         r->ServerInfoDotNet->aipServerAddrs = dns_addr_array_to_ip4_array(mem_ctx,
273                                                                                           serverinfo->aipServerAddrs);
274                         r->ServerInfoDotNet->aipListenAddrs = dns_addr_array_to_ip4_array(mem_ctx,
275                                                                                           serverinfo->aipListenAddrs);
276                         r->ServerInfoDotNet->aipForwarders = ip4_array_copy(mem_ctx, serverinfo->aipForwarders);
277                         r->ServerInfoDotNet->aipLogFilter = ip4_array_copy(mem_ctx, serverinfo->aipLogFilter);
278                         r->ServerInfoDotNet->pwszLogFilePath = talloc_strdup(mem_ctx, serverinfo->pwszLogFilePath);
279                         r->ServerInfoDotNet->pszDomainName = talloc_strdup(mem_ctx, serverinfo->pszDomainName);
280                         r->ServerInfoDotNet->pszForestName = talloc_strdup(mem_ctx, serverinfo->pszForestName);
281                         r->ServerInfoDotNet->pszDomainDirectoryPartition = talloc_strdup(mem_ctx, serverinfo->pszDomainDirectoryPartition);
282                         r->ServerInfoDotNet->pszForestDirectoryPartition = talloc_strdup(mem_ctx, serverinfo->pszForestDirectoryPartition);
283                         r->ServerInfoDotNet->dwLogLevel = serverinfo->dwLogLevel;
284                         r->ServerInfoDotNet->dwDebugLevel = serverinfo->dwDebugLevel;
285                         r->ServerInfoDotNet->dwForwardTimeout = serverinfo->dwForwardTimeout;
286                         r->ServerInfoDotNet->dwRpcProtocol = serverinfo->dwRpcProtocol;
287                         r->ServerInfoDotNet->dwNameCheckFlag = serverinfo->dwNameCheckFlag;
288                         r->ServerInfoDotNet->cAddressAnswerLimit = serverinfo->cAddressAnswerLimit;
289                         r->ServerInfoDotNet->dwRecursionRetry = serverinfo->dwRecursionRetry;
290                         r->ServerInfoDotNet->dwRecursionTimeout = serverinfo->dwRecursionTimeout;
291                         r->ServerInfoDotNet->dwMaxCacheTtl = serverinfo->dwMaxCacheTtl;
292                         r->ServerInfoDotNet->dwDsPollingInterval = serverinfo->dwDsPollingInterval;
293                         r->ServerInfoDotNet->dwLocalNetPriorityNetMask = serverinfo->dwLocalNetPriorityNetMask;
294                         r->ServerInfoDotNet->dwScavengingInterval = serverinfo->dwScavengingInterval;
295                         r->ServerInfoDotNet->dwDefaultRefreshInterval = serverinfo->dwDefaultRefreshInterval;
296                         r->ServerInfoDotNet->dwDefaultNoRefreshInterval = serverinfo->dwDefaultNoRefreshInterval;
297                         r->ServerInfoDotNet->dwLastScavengeTime = serverinfo->dwLastScavengeTime;
298                         r->ServerInfoDotNet->dwEventLogLevel = serverinfo->dwEventLogLevel;
299                         r->ServerInfoDotNet->dwLogFileMaxSize = serverinfo->dwLogFileMaxSize;
300                         r->ServerInfoDotNet->dwDsForestVersion = serverinfo->dwDsForestVersion;
301                         r->ServerInfoDotNet->dwDsDomainVersion = serverinfo->dwDsDomainVersion;
302                         r->ServerInfoDotNet->dwDsDsaVersion = serverinfo->dwDsDsaVersion;
303                         r->ServerInfoDotNet->fAutoReverseZones = serverinfo->fAutoReverseZones;
304                         r->ServerInfoDotNet->fAutoCacheUpdate = serverinfo->fAutoCacheUpdate;
305                         r->ServerInfoDotNet->fRecurseAfterForwarding = serverinfo->fRecurseAfterForwarding;
306                         r->ServerInfoDotNet->fForwardDelegations = serverinfo->fForwardDelegations;
307                         r->ServerInfoDotNet->fNoRecursion = serverinfo->fNoRecursion;
308                         r->ServerInfoDotNet->fSecureResponses = serverinfo->fSecureResponses;
309                         r->ServerInfoDotNet->fRoundRobin = serverinfo->fRoundRobin;
310                         r->ServerInfoDotNet->fLocalNetPriority = serverinfo->fLocalNetPriority;
311                         r->ServerInfoDotNet->fBindSecondaries = serverinfo->fBindSecondaries;
312                         r->ServerInfoDotNet->fWriteAuthorityNs = serverinfo->fWriteAuthorityNs;
313                         r->ServerInfoDotNet->fStrictFileParsing = serverinfo->fStrictFileParsing;
314                         r->ServerInfoDotNet->fLooseWildcarding = serverinfo->fLooseWildcarding;
315                         r->ServerInfoDotNet->fDefaultAgingState = serverinfo->fDefaultAgingState;
316
317                 } else if (client_version == DNS_CLIENT_VERSION_LONGHORN) {
318                         *typeid = DNSSRV_TYPEID_SERVER_INFO;
319                         r->ServerInfo = talloc_zero(mem_ctx, struct DNS_RPC_SERVER_INFO_LONGHORN);
320
321                         r->ServerInfo->dwRpcStructureVersion = 0x02;
322                         r->ServerInfo->dwVersion = serverinfo->dwVersion;
323                         r->ServerInfo->fBootMethod = serverinfo->fBootMethod;
324                         r->ServerInfo->fAdminConfigured = serverinfo->fAdminConfigured;
325                         r->ServerInfo->fAllowUpdate = serverinfo->fAllowUpdate;
326                         r->ServerInfo->fDsAvailable = serverinfo->fDsAvailable;
327                         r->ServerInfo->pszServerName = talloc_strdup(mem_ctx, serverinfo->pszServerName);
328                         r->ServerInfo->pszDsContainer = talloc_strdup(mem_ctx, serverinfo->pszDsContainer);
329                         r->ServerInfo->aipServerAddrs = serverinfo->aipServerAddrs;
330                         r->ServerInfo->aipListenAddrs = serverinfo->aipListenAddrs;
331                         r->ServerInfo->aipForwarders = ip4_array_to_dns_addr_array(mem_ctx, serverinfo->aipForwarders);
332                         r->ServerInfo->aipLogFilter = ip4_array_to_dns_addr_array(mem_ctx, serverinfo->aipLogFilter);
333                         r->ServerInfo->pwszLogFilePath = talloc_strdup(mem_ctx, serverinfo->pwszLogFilePath);
334                         r->ServerInfo->pszDomainName = talloc_strdup(mem_ctx, serverinfo->pszDomainName);
335                         r->ServerInfo->pszForestName = talloc_strdup(mem_ctx, serverinfo->pszForestName);
336                         r->ServerInfo->pszDomainDirectoryPartition = talloc_strdup(mem_ctx, serverinfo->pszDomainDirectoryPartition);
337                         r->ServerInfo->pszForestDirectoryPartition = talloc_strdup(mem_ctx, serverinfo->pszForestDirectoryPartition);
338                         r->ServerInfo->dwLogLevel = serverinfo->dwLogLevel;
339                         r->ServerInfo->dwDebugLevel = serverinfo->dwDebugLevel;
340                         r->ServerInfo->dwForwardTimeout = serverinfo->dwForwardTimeout;
341                         r->ServerInfo->dwRpcProtocol = serverinfo->dwRpcProtocol;
342                         r->ServerInfo->dwNameCheckFlag = serverinfo->dwNameCheckFlag;
343                         r->ServerInfo->cAddressAnswerLimit = serverinfo->cAddressAnswerLimit;
344                         r->ServerInfo->dwRecursionRetry = serverinfo->dwRecursionRetry;
345                         r->ServerInfo->dwRecursionTimeout = serverinfo->dwRecursionTimeout;
346                         r->ServerInfo->dwMaxCacheTtl = serverinfo->dwMaxCacheTtl;
347                         r->ServerInfo->dwDsPollingInterval = serverinfo->dwDsPollingInterval;
348                         r->ServerInfo->dwLocalNetPriorityNetMask = serverinfo->dwLocalNetPriorityNetMask;
349                         r->ServerInfo->dwScavengingInterval = serverinfo->dwScavengingInterval;
350                         r->ServerInfo->dwDefaultRefreshInterval = serverinfo->dwDefaultRefreshInterval;
351                         r->ServerInfo->dwDefaultNoRefreshInterval = serverinfo->dwDefaultNoRefreshInterval;
352                         r->ServerInfo->dwLastScavengeTime = serverinfo->dwLastScavengeTime;
353                         r->ServerInfo->dwEventLogLevel = serverinfo->dwEventLogLevel;
354                         r->ServerInfo->dwLogFileMaxSize = serverinfo->dwLogFileMaxSize;
355                         r->ServerInfo->dwDsForestVersion = serverinfo->dwDsForestVersion;
356                         r->ServerInfo->dwDsDomainVersion = serverinfo->dwDsDomainVersion;
357                         r->ServerInfo->dwDsDsaVersion = serverinfo->dwDsDsaVersion;
358                         r->ServerInfo->fReadOnlyDC = serverinfo->fReadOnlyDC;
359                         r->ServerInfo->fAutoReverseZones = serverinfo->fAutoReverseZones;
360                         r->ServerInfo->fAutoCacheUpdate = serverinfo->fAutoCacheUpdate;
361                         r->ServerInfo->fRecurseAfterForwarding = serverinfo->fRecurseAfterForwarding;
362                         r->ServerInfo->fForwardDelegations = serverinfo->fForwardDelegations;
363                         r->ServerInfo->fNoRecursion = serverinfo->fNoRecursion;
364                         r->ServerInfo->fSecureResponses = serverinfo->fSecureResponses;
365                         r->ServerInfo->fRoundRobin = serverinfo->fRoundRobin;
366                         r->ServerInfo->fLocalNetPriority = serverinfo->fLocalNetPriority;
367                         r->ServerInfo->fBindSecondaries = serverinfo->fBindSecondaries;
368                         r->ServerInfo->fWriteAuthorityNs = serverinfo->fWriteAuthorityNs;
369                         r->ServerInfo->fStrictFileParsing = serverinfo->fStrictFileParsing;
370                         r->ServerInfo->fLooseWildcarding = serverinfo->fLooseWildcarding;
371                         r->ServerInfo->fDefaultAgingState = serverinfo->fDefaultAgingState;
372                 }
373                 return WERR_OK;
374         }
375
376         is_integer = 0;
377         answer_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 = 0;
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                         if (!W_ERROR_IS_OK(status)) {
1731                                 talloc_free(tmp_ctx);
1732                                 return status;
1733                         }
1734                 }
1735         }
1736
1737         talloc_free(tmp_ctx);
1738
1739         *buffer_length = ndr_size_DNS_RPC_RECORDS_ARRAY(recs, 0);
1740         *buffer = recs;
1741
1742         return WERR_OK;
1743 }
1744
1745
1746 static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate,
1747                                         TALLOC_CTX *mem_ctx,
1748                                         struct dnsserver_zone *z,
1749                                         unsigned int client_version,
1750                                         const char *node_name,
1751                                         const char *start_child,
1752                                         enum dns_record_type record_type,
1753                                         unsigned int select_flag,
1754                                         const char *filter_start,
1755                                         const char *filter_stop,
1756                                         unsigned int *buffer_length,
1757                                         struct DNS_RPC_RECORDS_ARRAY **buffer)
1758 {
1759         TALLOC_CTX *tmp_ctx;
1760         char *name;
1761         const char * const attrs[] = { "name", "dnsRecord", NULL };
1762         struct ldb_result *res;
1763         struct DNS_RPC_RECORDS_ARRAY *recs;
1764         char **add_names = NULL;
1765         char *rname;
1766         int add_count = 0;
1767         int i, ret, len;
1768         WERROR status;
1769         struct dns_tree *tree, *base, *node;
1770
1771         tmp_ctx = talloc_new(mem_ctx);
1772         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1773
1774         name = dns_split_node_name(tmp_ctx, node_name, z->name);
1775         W_ERROR_HAVE_NO_MEMORY_AND_FREE(name, tmp_ctx);
1776
1777         /* search all records under parent tree */
1778         if (strcasecmp(name, z->name) == 0) {
1779                 ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z->zone_dn,
1780                                  LDB_SCOPE_ONELEVEL, attrs,
1781                                  "(&(objectClass=dnsNode)(!(dNSTombstoned=TRUE)))");
1782         } else {
1783                 char *encoded_name
1784                         = ldb_binary_encode_string(tmp_ctx, name);
1785                 ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z->zone_dn,
1786                                  LDB_SCOPE_ONELEVEL, attrs,
1787                                  "(&(objectClass=dnsNode)(|(name=%s)(name=*.%s))(!(dNSTombstoned=TRUE)))",
1788                                  encoded_name, encoded_name);
1789         }
1790         if (ret != LDB_SUCCESS) {
1791                 talloc_free(tmp_ctx);
1792                 return WERR_INTERNAL_DB_ERROR;
1793         }
1794         if (res->count == 0) {
1795                 talloc_free(tmp_ctx);
1796                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1797         }
1798
1799         recs = talloc_zero(mem_ctx, struct DNS_RPC_RECORDS_ARRAY);
1800         W_ERROR_HAVE_NO_MEMORY_AND_FREE(recs, tmp_ctx);
1801
1802         /* Sort the names, so that the first record is the parent record */
1803         ldb_qsort(res->msgs, res->count, sizeof(struct ldb_message *), name,
1804                         (ldb_qsort_cmp_fn_t)dns_name_compare);
1805
1806         /* Build a tree of name components from dns name */
1807         if (strcasecmp(name, z->name) == 0) {
1808                 tree = dns_build_tree(tmp_ctx, "@", res);
1809         } else {
1810                 tree = dns_build_tree(tmp_ctx, name, res);
1811         }
1812         W_ERROR_HAVE_NO_MEMORY_AND_FREE(tree, tmp_ctx);
1813
1814         /* Find the parent record in the tree */
1815         base = tree;
1816         while (base->level != -1) {
1817                 base = base->children[0];
1818         }
1819
1820         /* Add the parent record with blank name */
1821         if (!(select_flag & DNS_RPC_VIEW_ONLY_CHILDREN)) {
1822                 status = dns_fill_records_array(tmp_ctx, z, record_type,
1823                                                 select_flag, NULL,
1824                                                 base->data, 0,
1825                                                 recs, &add_names, &add_count);
1826                 if (!W_ERROR_IS_OK(status)) {
1827                         talloc_free(tmp_ctx);
1828                         return status;
1829                 }
1830         }
1831
1832         /* Add all the children records */
1833         if (!(select_flag & DNS_RPC_VIEW_NO_CHILDREN)) {
1834                 for (i=0; i<base->num_children; i++) {
1835                         node = base->children[i];
1836
1837                         status = dns_fill_records_array(tmp_ctx, z, record_type,
1838                                                         select_flag, node->name,
1839                                                         node->data, node->num_children,
1840                                                         recs, &add_names, &add_count);
1841                         if (!W_ERROR_IS_OK(status)) {
1842                                 talloc_free(tmp_ctx);
1843                                 return status;
1844                         }
1845                 }
1846         }
1847
1848         talloc_free(res);
1849         talloc_free(tree);
1850         talloc_free(name);
1851
1852         /* Add any additional records */
1853         if (select_flag & DNS_RPC_VIEW_ADDITIONAL_DATA) {
1854                 for (i=0; i<add_count; i++) {
1855                         struct dnsserver_zone *z2;
1856
1857                         /* Search all the available zones for additional name */
1858                         for (z2 = dsstate->zones; z2; z2 = z2->next) {
1859                                 char *encoded_name;
1860                                 name = dns_split_node_name(tmp_ctx, add_names[i], z2->name);
1861                                 encoded_name
1862                                         = ldb_binary_encode_string(tmp_ctx,
1863                                                                    name);
1864                                 ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z2->zone_dn,
1865                                                 LDB_SCOPE_ONELEVEL, attrs,
1866                                                 "(&(objectClass=dnsNode)(name=%s)(!(dNSTombstoned=TRUE)))",
1867                                                 encoded_name);
1868                                 talloc_free(name);
1869                                 if (ret != LDB_SUCCESS) {
1870                                         continue;
1871                                 }
1872                                 if (res->count == 1) {
1873                                         break;
1874                                 } else {
1875                                         talloc_free(res);
1876                                         continue;
1877                                 }
1878                         }
1879
1880                         len = strlen(add_names[i]);
1881                         if (add_names[i][len-1] == '.') {
1882                                 rname = talloc_strdup(tmp_ctx, add_names[i]);
1883                         } else {
1884                                 rname = talloc_asprintf(tmp_ctx, "%s.", add_names[i]);
1885                         }
1886                         status = dns_fill_records_array(tmp_ctx, NULL, DNS_TYPE_A,
1887                                                         select_flag, rname,
1888                                                         res->msgs[0], 0, recs,
1889                                                         NULL, NULL);
1890                         talloc_free(rname);
1891                         talloc_free(res);
1892                         if (!W_ERROR_IS_OK(status)) {
1893                                 talloc_free(tmp_ctx);
1894                                 return status;
1895                         }
1896                 }
1897         }
1898
1899         *buffer_length = ndr_size_DNS_RPC_RECORDS_ARRAY(recs, 0);
1900         *buffer = recs;
1901
1902         return WERR_OK;
1903 }
1904
1905 /*
1906  * Check str1 + '.' + str2 = name, for example:
1907  * ("dc0", "example.com", "dc0.example.com") = true
1908  */
1909 static bool cname_self_reference(const char* node_name,
1910                                  const char* zone_name,
1911                                  struct DNS_RPC_NAME name) {
1912         size_t node_len, zone_len;
1913
1914         if (node_name == NULL || zone_name == NULL) {
1915                 return false;
1916         }
1917
1918         node_len = strlen(node_name);
1919         zone_len = strlen(zone_name);
1920
1921         if (node_len == 0 ||
1922             zone_len == 0 ||
1923             (name.len != node_len + zone_len + 1)) {
1924                 return false;
1925         }
1926
1927         if (strncmp(node_name, name.str, node_len) == 0 &&
1928             name.str[node_len] == '.' &&
1929             strncmp(zone_name, name.str + node_len + 1, zone_len) == 0) {
1930                 return true;
1931         }
1932
1933         return false;
1934 }
1935
1936 /* dnsserver update function */
1937
1938 static WERROR dnsserver_update_record(struct dnsserver_state *dsstate,
1939                                         TALLOC_CTX *mem_ctx,
1940                                         struct dnsserver_zone *z,
1941                                         unsigned int client_version,
1942                                         const char *node_name,
1943                                         struct DNS_RPC_RECORD_BUF *add_buf,
1944                                         struct DNS_RPC_RECORD_BUF *del_buf)
1945 {
1946         TALLOC_CTX *tmp_ctx;
1947         char *name;
1948         WERROR status;
1949
1950         tmp_ctx = talloc_new(mem_ctx);
1951         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1952
1953         /* If node_name is @ or zone name, dns record is @ */
1954         if (strcmp(node_name, "@") == 0 ||
1955             strcmp(node_name, ".") == 0 ||
1956             strcasecmp(node_name, z->name) == 0) {
1957                 name = talloc_strdup(tmp_ctx, "@");
1958         } else {
1959                 name = dns_split_node_name(tmp_ctx, node_name, z->name);
1960         }
1961         W_ERROR_HAVE_NO_MEMORY_AND_FREE(name, tmp_ctx);
1962
1963         /* CNAMEs can't point to themselves */
1964         if (add_buf != NULL && add_buf->rec.wType == DNS_TYPE_CNAME) {
1965                 if (cname_self_reference(node_name, z->name, add_buf->rec.data.name)) {
1966                         return WERR_DNS_ERROR_CNAME_LOOP;
1967                 }
1968         }
1969
1970         if (add_buf != NULL) {
1971                 if (del_buf == NULL) {
1972                         /* Add record */
1973                         status = dnsserver_db_add_record(tmp_ctx, dsstate->samdb,
1974                                                                 z, name,
1975                                                                 &add_buf->rec);
1976                 } else {
1977                         /* Update record */
1978                         status = dnsserver_db_update_record(tmp_ctx, dsstate->samdb,
1979                                                                 z, name,
1980                                                                 &add_buf->rec,
1981                                                                 &del_buf->rec);
1982                 }
1983         } else {
1984                 if (del_buf == NULL) {
1985                         /* Add empty node */
1986                         status = dnsserver_db_add_empty_node(tmp_ctx, dsstate->samdb,
1987                                                                 z, name);
1988                 } else {
1989                         /* Delete record */
1990                         status = dnsserver_db_delete_record(tmp_ctx, dsstate->samdb,
1991                                                                 z, name,
1992                                                                 &del_buf->rec);
1993                 }
1994         }
1995
1996         talloc_free(tmp_ctx);
1997         return status;
1998 }
1999
2000
2001 /* dnsserver interface functions */
2002
2003 static WERROR dcesrv_DnssrvOperation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvOperation *r)
2004 {
2005         struct dnsserver_state *dsstate;
2006         struct dnsserver_zone *z = NULL;
2007         uint32_t request_filter = 0;
2008         WERROR ret;
2009
2010         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
2011                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
2012         }
2013
2014         if (r->in.dwContext == 0) {
2015                 if (r->in.pszZone != NULL) {
2016                         request_filter = dnsserver_zone_to_request_filter(r->in.pszZone);
2017                 }
2018         } else {
2019                 request_filter = r->in.dwContext;
2020         }
2021
2022         if (r->in.pszZone == NULL) {
2023                 ret = dnsserver_operate_server(dsstate, mem_ctx,
2024                                                 r->in.pszOperation,
2025                                                 DNS_CLIENT_VERSION_W2K,
2026                                                 r->in.dwTypeId,
2027                                                 &r->in.pData);
2028         } else {
2029                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
2030                 if (z == NULL && request_filter == 0) {
2031                         return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
2032                 }
2033
2034                 ret = dnsserver_operate_zone(dsstate, mem_ctx, z,
2035                                                 request_filter,
2036                                                 r->in.pszOperation,
2037                                                 DNS_CLIENT_VERSION_W2K,
2038                                                 r->in.dwTypeId,
2039                                                 &r->in.pData);
2040         }
2041
2042         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2043                 NDR_PRINT_FUNCTION_DEBUG(DnssrvOperation, NDR_IN, r);
2044         }
2045         return ret;
2046 }
2047
2048 static WERROR dcesrv_DnssrvQuery(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvQuery *r)
2049 {
2050         struct dnsserver_state *dsstate;
2051         struct dnsserver_zone *z;
2052         WERROR ret;
2053
2054         ZERO_STRUCTP(r->out.pdwTypeId);
2055         ZERO_STRUCTP(r->out.ppData);
2056
2057         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
2058                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
2059         }
2060
2061         if (r->in.pszZone == NULL) {
2062                 /* FIXME: DNS Server Configuration Access Control List */
2063                 ret = dnsserver_query_server(dsstate, mem_ctx,
2064                                                 r->in.pszOperation,
2065                                                 DNS_CLIENT_VERSION_W2K,
2066                                                 r->out.pdwTypeId,
2067                                                 r->out.ppData);
2068         } else {
2069                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
2070                 if (z == NULL) {
2071                         return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
2072                 }
2073
2074                 ret = dnsserver_query_zone(dsstate, mem_ctx, z,
2075                                                 r->in.pszOperation,
2076                                                 DNS_CLIENT_VERSION_W2K,
2077                                                 r->out.pdwTypeId,
2078                                                 r->out.ppData);
2079         }
2080
2081         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2082                 NDR_PRINT_FUNCTION_DEBUG(DnssrvQuery, NDR_IN, r);
2083         }
2084         return ret;
2085 }
2086
2087 static WERROR dcesrv_DnssrvComplexOperation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvComplexOperation *r)
2088 {
2089         struct dnsserver_state *dsstate;
2090         struct dnsserver_zone *z;
2091         WERROR ret;
2092
2093         ZERO_STRUCTP(r->out.pdwTypeOut);
2094         ZERO_STRUCTP(r->out.ppDataOut);
2095
2096         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
2097                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
2098         }
2099
2100         if (r->in.pszZone == NULL) {
2101                 /* Server operation */
2102                 ret = dnsserver_complex_operate_server(dsstate, mem_ctx,
2103                                                         r->in.pszOperation,
2104                                                         DNS_CLIENT_VERSION_W2K,
2105                                                         r->in.dwTypeIn,
2106                                                         &r->in.pDataIn,
2107                                                         r->out.pdwTypeOut,
2108                                                         r->out.ppDataOut);
2109         } else {
2110                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
2111                 if (z == NULL) {
2112                         return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
2113                 }
2114
2115                 ret = dnsserver_complex_operate_zone(dsstate, mem_ctx, z,
2116                                                         r->in.pszOperation,
2117                                                         DNS_CLIENT_VERSION_W2K,
2118                                                         r->in.dwTypeIn,
2119                                                         &r->in.pDataIn,
2120                                                         r->out.pdwTypeOut,
2121                                                         r->out.ppDataOut);
2122         }
2123
2124         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2125                 NDR_PRINT_FUNCTION_DEBUG(DnssrvComplexOperation, NDR_IN, r);
2126         }
2127         return ret;
2128 }
2129
2130 static WERROR dcesrv_DnssrvEnumRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvEnumRecords *r)
2131 {
2132         struct dnsserver_state *dsstate;
2133         struct dnsserver_zone *z;
2134         WERROR ret;
2135
2136         ZERO_STRUCTP(r->out.pdwBufferLength);
2137         ZERO_STRUCTP(r->out.pBuffer);
2138
2139         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
2140                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
2141         }
2142
2143         if (r->in.pszZone == NULL) {
2144                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2145         }
2146
2147         if (strcasecmp(r->in.pszZone, "..RootHints") == 0) {
2148                 ret = dnsserver_enumerate_root_records(dsstate, mem_ctx,
2149                                         DNS_CLIENT_VERSION_W2K,
2150                                         r->in.pszNodeName,
2151                                         r->in.wRecordType,
2152                                         r->in.fSelectFlag,
2153                                         r->out.pdwBufferLength,
2154                                         r->out.pBuffer);
2155         } else {
2156                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
2157                 if (z == NULL) {
2158                         return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2159                 }
2160
2161                 ret = dnsserver_enumerate_records(dsstate, mem_ctx, z,
2162                                         DNS_CLIENT_VERSION_W2K,
2163                                         r->in.pszNodeName,
2164                                         r->in.pszStartChild,
2165                                         r->in.wRecordType,
2166                                         r->in.fSelectFlag,
2167                                         r->in.pszFilterStart,
2168                                         r->in.pszFilterStop,
2169                                         r->out.pdwBufferLength,
2170                                         r->out.pBuffer);
2171         }
2172
2173         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2174                 NDR_PRINT_FUNCTION_DEBUG(DnssrvEnumRecords, NDR_IN, r);
2175         }
2176         return ret;
2177 }
2178
2179 static WERROR dcesrv_DnssrvUpdateRecord(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvUpdateRecord *r)
2180 {
2181         struct dnsserver_state *dsstate;
2182         struct dnsserver_zone *z;
2183         WERROR ret;
2184
2185         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
2186                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
2187         }
2188
2189         if (r->in.pszZone == NULL) {
2190                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2191         }
2192
2193         z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
2194         if (z == NULL) {
2195                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2196         }
2197
2198         ret = dnsserver_update_record(dsstate, mem_ctx, z,
2199                                         DNS_CLIENT_VERSION_W2K,
2200                                         r->in.pszNodeName,
2201                                         r->in.pAddRecord,
2202                                         r->in.pDeleteRecord);
2203
2204         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2205                 NDR_PRINT_FUNCTION_DEBUG(DnssrvUpdateRecord, NDR_IN, r);
2206         }
2207         return ret;
2208 }
2209
2210 static WERROR dcesrv_DnssrvOperation2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvOperation2 *r)
2211 {
2212         struct dnsserver_state *dsstate;
2213         struct dnsserver_zone *z = NULL;
2214         uint32_t request_filter = 0;
2215         WERROR ret;
2216
2217         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
2218                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
2219         }
2220
2221         if (r->in.dwContext == 0) {
2222                 if (r->in.pszZone != NULL) {
2223                         request_filter = dnsserver_zone_to_request_filter(r->in.pszZone);
2224                 }
2225         } else {
2226                 request_filter = r->in.dwContext;
2227         }
2228
2229         if (r->in.pszZone == NULL) {
2230                 ret = dnsserver_operate_server(dsstate, mem_ctx,
2231                                                 r->in.pszOperation,
2232                                                 r->in.dwClientVersion,
2233                                                 r->in.dwTypeId,
2234                                                 &r->in.pData);
2235         } else {
2236                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
2237                 if (z == NULL && request_filter == 0) {
2238                         return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
2239                 }
2240
2241                 ret = dnsserver_operate_zone(dsstate, mem_ctx, z,
2242                                                 request_filter,
2243                                                 r->in.pszOperation,
2244                                                 r->in.dwClientVersion,
2245                                                 r->in.dwTypeId,
2246                                                 &r->in.pData);
2247         }
2248
2249         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2250                 NDR_PRINT_FUNCTION_DEBUG(DnssrvOperation2, NDR_IN, r);
2251         }
2252         return ret;
2253 }
2254
2255 static WERROR dcesrv_DnssrvQuery2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvQuery2 *r)
2256 {
2257         struct dnsserver_state *dsstate;
2258         struct dnsserver_zone *z;
2259         WERROR ret;
2260
2261         ZERO_STRUCTP(r->out.pdwTypeId);
2262         ZERO_STRUCTP(r->out.ppData);
2263
2264         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
2265                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
2266         }
2267
2268         if (r->in.pszZone == NULL) {
2269                 /* FIXME: DNS Server Configuration Access Control List */
2270                 ret = dnsserver_query_server(dsstate, mem_ctx,
2271                                                 r->in.pszOperation,
2272                                                 r->in.dwClientVersion,
2273                                                 r->out.pdwTypeId,
2274                                                 r->out.ppData);
2275         } else {
2276                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
2277                 if (z == NULL) {
2278                         return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
2279                 }
2280
2281                 ret = dnsserver_query_zone(dsstate, mem_ctx, z,
2282                                         r->in.pszOperation,
2283                                         r->in.dwClientVersion,
2284                                         r->out.pdwTypeId,
2285                                         r->out.ppData);
2286         }
2287
2288         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2289                 NDR_PRINT_FUNCTION_DEBUG(DnssrvQuery2, NDR_IN, r);
2290         }
2291         return ret;
2292 }
2293
2294 static WERROR dcesrv_DnssrvComplexOperation2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvComplexOperation2 *r)
2295 {
2296         struct dnsserver_state *dsstate;
2297         struct dnsserver_zone *z;
2298         WERROR ret;
2299
2300         ZERO_STRUCTP(r->out.pdwTypeOut);
2301         ZERO_STRUCTP(r->out.ppDataOut);
2302
2303         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
2304                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
2305         }
2306
2307         if (r->in.pszZone == NULL) {
2308                 /* Server operation */
2309                 ret =  dnsserver_complex_operate_server(dsstate, mem_ctx,
2310                                                         r->in.pszOperation,
2311                                                         r->in.dwClientVersion,
2312                                                         r->in.dwTypeIn,
2313                                                         &r->in.pDataIn,
2314                                                         r->out.pdwTypeOut,
2315                                                         r->out.ppDataOut);
2316         } else {
2317
2318                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
2319                 if (z == NULL) {
2320                         return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
2321                 }
2322
2323                 ret = dnsserver_complex_operate_zone(dsstate, mem_ctx, z,
2324                                                         r->in.pszOperation,
2325                                                         r->in.dwClientVersion,
2326                                                         r->in.dwTypeIn,
2327                                                         &r->in.pDataIn,
2328                                                         r->out.pdwTypeOut,
2329                                                         r->out.ppDataOut);
2330         }
2331
2332         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2333                 NDR_PRINT_FUNCTION_DEBUG(DnssrvComplexOperation2, NDR_IN, r);
2334         }
2335         return ret;
2336 }
2337
2338 static WERROR dcesrv_DnssrvEnumRecords2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvEnumRecords2 *r)
2339 {
2340         struct dnsserver_state *dsstate;
2341         struct dnsserver_zone *z;
2342         WERROR ret;
2343
2344         ZERO_STRUCTP(r->out.pdwBufferLength);
2345         ZERO_STRUCTP(r->out.pBuffer);
2346
2347         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
2348                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
2349         }
2350
2351         if (r->in.pszZone == NULL) {
2352                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2353         }
2354
2355         if (strcasecmp(r->in.pszZone, "..RootHints") == 0) {
2356                 ret =  dnsserver_enumerate_root_records(dsstate, mem_ctx,
2357                                         r->in.dwClientVersion,
2358                                         r->in.pszNodeName,
2359                                         r->in.wRecordType,
2360                                         r->in.fSelectFlag,
2361                                         r->out.pdwBufferLength,
2362                                         r->out.pBuffer);
2363         } else {
2364                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
2365                 if (z == NULL) {
2366                         return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2367                 }
2368
2369                 ret =  dnsserver_enumerate_records(dsstate, mem_ctx, z,
2370                                         r->in.dwClientVersion,
2371                                         r->in.pszNodeName,
2372                                         r->in.pszStartChild,
2373                                         r->in.wRecordType,
2374                                         r->in.fSelectFlag,
2375                                         r->in.pszFilterStart,
2376                                         r->in.pszFilterStop,
2377                                         r->out.pdwBufferLength,
2378                                         r->out.pBuffer);
2379
2380         }
2381
2382         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2383                 NDR_PRINT_FUNCTION_DEBUG(DnssrvEnumRecords2, NDR_IN, r);
2384         }
2385         return ret;
2386 }
2387
2388 static WERROR dcesrv_DnssrvUpdateRecord2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvUpdateRecord2 *r)
2389 {
2390         struct dnsserver_state *dsstate;
2391         struct dnsserver_zone *z;
2392         WERROR ret;
2393
2394         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
2395                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
2396         }
2397
2398         if (r->in.pszZone == NULL) {
2399                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2400         }
2401
2402         z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
2403         if (z == NULL) {
2404                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2405         }
2406
2407         ret = dnsserver_update_record(dsstate, mem_ctx, z,
2408                                         r->in.dwClientVersion,
2409                                         r->in.pszNodeName,
2410                                         r->in.pAddRecord,
2411                                         r->in.pDeleteRecord);
2412
2413         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2414                 NDR_PRINT_FUNCTION_DEBUG(DnssrvUpdateRecord2, NDR_IN, r);
2415         }
2416         return ret;
2417 }
2418
2419 /* include the generated boilerplate */
2420 #include "librpc/gen_ndr/ndr_dnsserver_s.c"