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