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