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