345cfb814e859c54774e6f9baf9b61ffb404df0e
[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                         if (rout->ZoneListW2K->ZoneArray == NULL) {
1246                                 talloc_free(zlist);
1247                                 return WERR_NOMEM;
1248                         }
1249
1250                         for (i=0; i<zcount; i++) {
1251                                 rout->ZoneListW2K->ZoneArray[i] = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_W2K);
1252
1253                                 rout->ZoneListW2K->ZoneArray[i]->pszZoneName = talloc_strdup(mem_ctx, zlist[i]->name);
1254                                 rout->ZoneListW2K->ZoneArray[i]->Flags = zlist[i]->zoneinfo->Flags;
1255                                 rout->ZoneListW2K->ZoneArray[i]->ZoneType = zlist[i]->zoneinfo->dwZoneType;
1256                                 rout->ZoneListW2K->ZoneArray[i]->Version = zlist[i]->zoneinfo->Version;
1257                         }
1258                         rout->ZoneListW2K->dwZoneCount = zcount;
1259
1260                 } else {
1261                         *typeid_out = DNSSRV_TYPEID_ZONE_LIST;
1262                         rout->ZoneList = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_LIST_DOTNET);
1263
1264                         if (zcount == 0) {
1265                                 rout->ZoneList->dwRpcStructureVersion = 1;
1266                                 rout->ZoneList->dwZoneCount = 0;
1267                                 rout->ZoneList->ZoneArray = NULL;
1268
1269                                 return WERR_OK;
1270                         }
1271
1272                         rout->ZoneList->ZoneArray = talloc_zero_array(mem_ctx, struct DNS_RPC_ZONE_DOTNET *, zcount);
1273                         if (rout->ZoneList->ZoneArray == NULL) {
1274                                 talloc_free(zlist);
1275                                 return WERR_NOMEM;
1276                         }
1277
1278                         for (i=0; i<zcount; i++) {
1279                                 rout->ZoneList->ZoneArray[i] = talloc_zero(mem_ctx, struct DNS_RPC_ZONE_DOTNET);
1280
1281                                 rout->ZoneList->ZoneArray[i]->dwRpcStructureVersion = 1;
1282                                 rout->ZoneList->ZoneArray[i]->pszZoneName = talloc_strdup(mem_ctx, zlist[i]->name);
1283                                 rout->ZoneList->ZoneArray[i]->Flags = zlist[i]->zoneinfo->Flags;
1284                                 rout->ZoneList->ZoneArray[i]->ZoneType = zlist[i]->zoneinfo->dwZoneType;
1285                                 rout->ZoneList->ZoneArray[i]->Version = zlist[i]->zoneinfo->Version;
1286                                 rout->ZoneList->ZoneArray[i]->dwDpFlags = zlist[i]->partition->dwDpFlags;
1287                                 rout->ZoneList->ZoneArray[i]->pszDpFqdn = talloc_strdup(mem_ctx, zlist[i]->partition->pszDpFqdn);
1288                         }
1289                         rout->ZoneList->dwRpcStructureVersion = 1;
1290                         rout->ZoneList->dwZoneCount = zcount;
1291                 }
1292                 talloc_free(zlist);
1293                 return WERR_OK;
1294         } else if (strcasecmp(operation, "EnumZones2") == 0) {
1295                 valid_operation = true;
1296         } else if (strcasecmp(operation, "EnumDirectoryPartitions") == 0) {
1297                 if (typeid_in != DNSSRV_TYPEID_DWORD) {
1298                         return WERR_DNS_ERROR_INVALID_PROPERTY;
1299                 }
1300
1301                 *typeid_out = DNSSRV_TYPEID_DP_LIST;
1302                 rout->DirectoryPartitionList = talloc_zero(mem_ctx, struct DNS_RPC_DP_LIST);
1303
1304                 if (rin->Dword != 0) {
1305                         rout->DirectoryPartitionList->dwDpCount = 0;
1306                         rout->DirectoryPartitionList->DpArray = NULL;
1307                 } else {
1308                         struct DNS_RPC_DP_ENUM **dplist;
1309                         struct dnsserver_partition *p;
1310                         int pcount = 2;
1311
1312                         dplist = talloc_zero_array(mem_ctx, struct DNS_RPC_DP_ENUM *, pcount);
1313                         if (dplist == NULL) {
1314                                 return WERR_NOMEM;
1315                         }
1316
1317                         p = dsstate->partitions;
1318                         for (i=0; i<pcount; i++) {
1319                                 dplist[i] = talloc_zero(dplist, struct DNS_RPC_DP_ENUM);
1320
1321                                 dplist[i]->pszDpFqdn = talloc_strdup(mem_ctx, p->pszDpFqdn);
1322                                 dplist[i]->dwFlags = p->dwDpFlags;
1323                                 dplist[i]->dwZoneCount = p->zones_count;
1324                                 p = p->next;
1325                         }
1326
1327                         rout->DirectoryPartitionList->dwDpCount = pcount;
1328                         rout->DirectoryPartitionList->DpArray = dplist;
1329                 }
1330                 return WERR_OK;
1331         } else if (strcasecmp(operation, "DirectoryPartitionInfo") == 0) {
1332                 valid_operation = true;
1333         } else if (strcasecmp(operation, "Statistics") == 0) {
1334                 valid_operation = true;
1335         } else if (strcasecmp(operation, "IpValidate") == 0) {
1336                 valid_operation = true;
1337         }
1338
1339         if (valid_operation) {
1340                 DEBUG(0, ("dnsserver: server complex operation '%s' not implemented", operation));
1341                 return WERR_CALL_NOT_IMPLEMENTED;
1342         }
1343
1344         DEBUG(0, ("dnsserver: invalid server complex operation '%s'", operation));
1345         return WERR_DNS_ERROR_INVALID_PROPERTY;
1346 }
1347
1348 /* [MS-DNSP].pdf Section 3.1.1.2 Zone Configuration Information */
1349 static WERROR dnsserver_operate_zone(struct dnsserver_state *dsstate,
1350                                         TALLOC_CTX *mem_ctx,
1351                                         struct dnsserver_zone *z,
1352                                         unsigned int request_filter,
1353                                         const char *operation,
1354                                         const unsigned int client_version,
1355                                         enum DNS_RPC_TYPEID typeid,
1356                                         union DNSSRV_RPC_UNION *r)
1357 {
1358         bool valid_operation = false;
1359
1360         if (strcasecmp(operation, "ResetDwordProperty") == 0) {
1361                 valid_operation = true;
1362         } else if (strcasecmp(operation, "ZoneTypeReset") == 0) {
1363                 valid_operation = true;
1364         } else if (strcasecmp(operation, "PauseZone") == 0) {
1365                 valid_operation = true;
1366         } else if (strcasecmp(operation, "ResumeZone") == 0) {
1367                 valid_operation = true;
1368         } else if (strcasecmp(operation, "DeleteZone") == 0) {
1369                 valid_operation = true;
1370         } else if (strcasecmp(operation, "ReloadZone") == 0) {
1371                 valid_operation = true;
1372         } else if (strcasecmp(operation, "RefreshZone") == 0) {
1373                 valid_operation = true;
1374         } else if (strcasecmp(operation, "ExpireZone") == 0) {
1375                 valid_operation = true;
1376         } else if (strcasecmp(operation, "IncrementVersion") == 0) {
1377                 valid_operation = true;
1378         } else if (strcasecmp(operation, "WriteBackFile") == 0) {
1379                 valid_operation = true;
1380         } else if (strcasecmp(operation, "DeleteZoneFromDs") == 0) {
1381                 valid_operation = true;
1382         } else if (strcasecmp(operation, "UpdateZoneFromDs") == 0) {
1383                 valid_operation = true;
1384         } else if (strcasecmp(operation, "ZoneExport") == 0) {
1385                 valid_operation = true;
1386         } else if (strcasecmp(operation, "ZoneChangeDirectoryPartition") == 0) {
1387                 valid_operation = true;
1388         } else if (strcasecmp(operation, "DeleteNode") == 0) {
1389                 valid_operation = true;
1390         } else if (strcasecmp(operation, "DeleteRecordSet") == 0) {
1391                 valid_operation = true;
1392         } else if (strcasecmp(operation, "ForceAgingOnNode") == 0) {
1393                 valid_operation = true;
1394         } else if (strcasecmp(operation, "DatabaseFile") == 0) {
1395                 valid_operation = true;
1396         } else if (strcasecmp(operation, "MasterServers") == 0) {
1397                 valid_operation = true;
1398         } else if (strcasecmp(operation, "LocalMasterServers") == 0) {
1399                 valid_operation = true;
1400         } else if (strcasecmp(operation, "NotifyServers") == 0) {
1401                 valid_operation = true;
1402         } else if (strcasecmp(operation, "SecondaryServers") == 0) {
1403                 valid_operation = true;
1404         } else if (strcasecmp(operation, "ScavengingServers") == 0) {
1405                 valid_operation = true;
1406         } else if (strcasecmp(operation, "AllowNSRecordsAutoCreation") == 0) {
1407                 valid_operation = true;
1408         } else if (strcasecmp(operation, "BreakOnNameUpdate") == 0) {
1409                 valid_operation = true;
1410         } else if (strcasecmp(operation, "ApplicationDirectoryPartition") == 0) {
1411                 valid_operation = true;
1412         }
1413
1414         if (valid_operation) {
1415                 DEBUG(0, ("dnsserver: zone operation '%s' not implemented", operation));
1416                 return WERR_CALL_NOT_IMPLEMENTED;
1417         }
1418
1419         DEBUG(0, ("dnsserver: invalid zone operation '%s'", operation));
1420         return WERR_DNS_ERROR_INVALID_PROPERTY;
1421 }
1422
1423 static WERROR dnsserver_complex_operate_zone(struct dnsserver_state *dsstate,
1424                                         TALLOC_CTX *mem_ctx,
1425                                         struct dnsserver_zone *z,
1426                                         const char *operation,
1427                                         const unsigned int client_version,
1428                                         enum DNS_RPC_TYPEID typeid_in,
1429                                         union DNSSRV_RPC_UNION *rin,
1430                                         enum DNS_RPC_TYPEID *typeid_out,
1431                                         union DNSSRV_RPC_UNION *rout)
1432 {
1433         if (strcasecmp(operation, "QueryDwordProperty") == 0) {
1434                 if (typeid_in == DNSSRV_TYPEID_LPSTR) {
1435                         return dnsserver_query_zone(dsstate, mem_ctx, z,
1436                                                 rin->String,
1437                                                 client_version,
1438                                                 typeid_out,
1439                                                 rout);
1440
1441                 }
1442         }
1443
1444         DEBUG(0,("dnsserver: Invalid zone operation %s", operation));
1445         return WERR_DNS_ERROR_INVALID_PROPERTY;
1446 }
1447
1448 /* dnsserver enumerate function */
1449
1450 static WERROR dnsserver_enumerate_root_records(struct dnsserver_state *dsstate,
1451                                         TALLOC_CTX *mem_ctx,
1452                                         unsigned int client_version,
1453                                         const char *node_name,
1454                                         enum dns_record_type record_type,
1455                                         unsigned int select_flag,
1456                                         unsigned int *buffer_length,
1457                                         struct DNS_RPC_RECORDS_ARRAY **buffer)
1458 {
1459         TALLOC_CTX *tmp_ctx;
1460         struct dnsserver_zone *z;
1461         const char * const attrs[] = { "name", "dnsRecord", NULL };
1462         struct ldb_result *res;
1463         struct DNS_RPC_RECORDS_ARRAY *recs;
1464         char **add_names;
1465         char *rname;
1466         int add_count;
1467         int i, ret, len;
1468         WERROR status;
1469
1470         tmp_ctx = talloc_new(mem_ctx);
1471         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1472
1473         z = dnsserver_find_zone(dsstate->zones, ".");
1474         if (z == NULL) {
1475                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1476         }
1477
1478         ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z->zone_dn,
1479                                 LDB_SCOPE_ONELEVEL, attrs, "(&(objectClass=dnsNode)(name=@))");
1480         if (ret != LDB_SUCCESS) {
1481                 talloc_free(tmp_ctx);
1482                 return WERR_INTERNAL_DB_ERROR;
1483         }
1484         if (res->count == 0) {
1485                 talloc_free(tmp_ctx);
1486                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1487         }
1488
1489         recs = talloc_zero(mem_ctx, struct DNS_RPC_RECORDS_ARRAY);
1490         W_ERROR_HAVE_NO_MEMORY_AND_FREE(recs, tmp_ctx);
1491
1492         add_names = NULL;
1493         add_count = 0;
1494
1495         for (i=0; i<res->count; i++) {
1496                 status = dns_fill_records_array(tmp_ctx, NULL, record_type,
1497                                                 select_flag, NULL,
1498                                                 res->msgs[i], 0, recs,
1499                                                 &add_names, &add_count);
1500                 if (!W_ERROR_IS_OK(status)) {
1501                         talloc_free(tmp_ctx);
1502                         return status;
1503                 }
1504         }
1505         talloc_free(res);
1506
1507         /* Add any additional records */
1508         if (select_flag & DNS_RPC_VIEW_ADDITIONAL_DATA) {
1509                 for (i=0; i<add_count; i++) {
1510                         ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z->zone_dn,
1511                                         LDB_SCOPE_ONELEVEL, attrs,
1512                                         "(&(objectClass=dnsNode)(name=%s))", add_names[i]);
1513                         if (ret != LDB_SUCCESS || res->count == 0) {
1514                                 talloc_free(res);
1515                                 continue;
1516                         }
1517
1518                         len = strlen(add_names[i]);
1519                         if (add_names[i][len-1] == '.') {
1520                                 rname = talloc_strdup(tmp_ctx, add_names[i]);
1521                         } else {
1522                                 rname = talloc_asprintf(tmp_ctx, "%s.", add_names[i]);
1523                         }
1524                         status = dns_fill_records_array(tmp_ctx, NULL, DNS_TYPE_A,
1525                                                         select_flag, rname,
1526                                                         res->msgs[0], 0, recs,
1527                                                         NULL, NULL);
1528                         talloc_free(rname);
1529                         talloc_free(res);
1530                 }
1531         }
1532
1533         talloc_free(tmp_ctx);
1534
1535         *buffer_length = ndr_size_DNS_RPC_RECORDS_ARRAY(recs, 0);
1536         *buffer = recs;
1537
1538         return WERR_OK;
1539 }
1540
1541
1542 static WERROR dnsserver_enumerate_records(struct dnsserver_state *dsstate,
1543                                         TALLOC_CTX *mem_ctx,
1544                                         struct dnsserver_zone *z,
1545                                         unsigned int client_version,
1546                                         const char *node_name,
1547                                         const char *start_child,
1548                                         enum dns_record_type record_type,
1549                                         unsigned int select_flag,
1550                                         const char *filter_start,
1551                                         const char *filter_stop,
1552                                         unsigned int *buffer_length,
1553                                         struct DNS_RPC_RECORDS_ARRAY **buffer)
1554 {
1555         TALLOC_CTX *tmp_ctx;
1556         char *name;
1557         const char * const attrs[] = { "name", "dnsRecord", NULL };
1558         struct ldb_result *res;
1559         struct DNS_RPC_RECORDS_ARRAY *recs;
1560         char **add_names = NULL;
1561         char *rname;
1562         int add_count = 0;
1563         int i, ret, len;
1564         WERROR status;
1565         struct dns_tree *tree, *base, *node;
1566
1567         tmp_ctx = talloc_new(mem_ctx);
1568         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1569
1570         name = dns_split_node_name(tmp_ctx, node_name, z->name);
1571         W_ERROR_HAVE_NO_MEMORY_AND_FREE(name, tmp_ctx);
1572
1573         /* search all records under parent tree */
1574         if (strcmp(name, z->name) == 0) {
1575                 ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z->zone_dn,
1576                                 LDB_SCOPE_ONELEVEL, attrs, "(objectClass=dnsNode)");
1577         } else {
1578                 ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z->zone_dn,
1579                                 LDB_SCOPE_ONELEVEL, attrs,
1580                                 "(&(objectClass=dnsNode)(|(name=%s)(name=*.%s)))",
1581                                 name, name);
1582         }
1583         if (ret != LDB_SUCCESS) {
1584                 talloc_free(tmp_ctx);
1585                 return WERR_INTERNAL_DB_ERROR;
1586         }
1587         if (res->count == 0) {
1588                 talloc_free(tmp_ctx);
1589                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1590         }
1591
1592         recs = talloc_zero(mem_ctx, struct DNS_RPC_RECORDS_ARRAY);
1593         W_ERROR_HAVE_NO_MEMORY_AND_FREE(recs, tmp_ctx);
1594
1595         /* Sort the names, so that the first record is the parent record */
1596         ldb_qsort(res->msgs, res->count, sizeof(struct ldb_message *), name,
1597                         (ldb_qsort_cmp_fn_t)dns_name_compare);
1598
1599         /* Build a tree of name components from dns name */
1600         if (strcmp(name, z->name) == 0) {
1601                 tree = dns_build_tree(tmp_ctx, "@", res);
1602         } else {
1603                 tree = dns_build_tree(tmp_ctx, name, res);
1604         }
1605         W_ERROR_HAVE_NO_MEMORY_AND_FREE(tree, tmp_ctx);
1606
1607         /* Find the parent record in the tree */
1608         base = tree;
1609         while (base->level != -1) {
1610                 base = base->children[0];
1611         }
1612
1613         /* Add the parent record with blank name */
1614         if (!(select_flag & DNS_RPC_VIEW_ONLY_CHILDREN)) {
1615                 status = dns_fill_records_array(tmp_ctx, z, record_type,
1616                                                 select_flag, NULL,
1617                                                 base->data, 0,
1618                                                 recs, &add_names, &add_count);
1619                 if (!W_ERROR_IS_OK(status)) {
1620                         talloc_free(tmp_ctx);
1621                         return status;
1622                 }
1623         }
1624
1625         /* Add all the children records */
1626         if (!(select_flag & DNS_RPC_VIEW_NO_CHILDREN)) {
1627                 for (i=0; i<base->num_children; i++) {
1628                         node = base->children[i];
1629
1630                         status = dns_fill_records_array(tmp_ctx, z, record_type,
1631                                                         select_flag, node->name,
1632                                                         node->data, node->num_children,
1633                                                         recs, &add_names, &add_count);
1634                         if (!W_ERROR_IS_OK(status)) {
1635                                 talloc_free(tmp_ctx);
1636                                 return status;
1637                         }
1638                 }
1639         }
1640
1641         talloc_free(res);
1642         talloc_free(tree);
1643         talloc_free(name);
1644
1645         /* Add any additional records */
1646         if (select_flag & DNS_RPC_VIEW_ADDITIONAL_DATA) {
1647                 for (i=0; i<add_count; i++) {
1648                         struct dnsserver_zone *z2;
1649
1650                         /* Search all the available zones for additional name */
1651                         for (z2 = dsstate->zones; z2; z2 = z2->next) {
1652                                 name = dns_split_node_name(tmp_ctx, add_names[i], z2->name);
1653                                 ret = ldb_search(dsstate->samdb, tmp_ctx, &res, z2->zone_dn,
1654                                                 LDB_SCOPE_ONELEVEL, attrs,
1655                                                 "(&(objectClass=dnsNode)(name=%s))", name);
1656                                 talloc_free(name);
1657                                 if (ret != LDB_SUCCESS) {
1658                                         continue;
1659                                 }
1660                                 if (res->count == 1) {
1661                                         break;
1662                                 } else {
1663                                         talloc_free(res);
1664                                         continue;
1665                                 }
1666                         }
1667
1668                         len = strlen(add_names[i]);
1669                         if (add_names[i][len-1] == '.') {
1670                                 rname = talloc_strdup(tmp_ctx, add_names[i]);
1671                         } else {
1672                                 rname = talloc_asprintf(tmp_ctx, "%s.", add_names[i]);
1673                         }
1674                         status = dns_fill_records_array(tmp_ctx, NULL, DNS_TYPE_A,
1675                                                         select_flag, rname,
1676                                                         res->msgs[0], 0, recs,
1677                                                         NULL, NULL);
1678                         talloc_free(rname);
1679                         talloc_free(res);
1680                 }
1681         }
1682
1683         *buffer_length = ndr_size_DNS_RPC_RECORDS_ARRAY(recs, 0);
1684         *buffer = recs;
1685
1686         return WERR_OK;
1687 }
1688
1689 /* dnsserver update function */
1690
1691 static WERROR dnsserver_update_record(struct dnsserver_state *dsstate,
1692                                         TALLOC_CTX *mem_ctx,
1693                                         struct dnsserver_zone *z,
1694                                         unsigned int client_version,
1695                                         const char *node_name,
1696                                         struct DNS_RPC_RECORD_BUF *add_buf,
1697                                         struct DNS_RPC_RECORD_BUF *del_buf)
1698 {
1699         TALLOC_CTX *tmp_ctx;
1700         char *name;
1701         WERROR status;
1702
1703         tmp_ctx = talloc_new(mem_ctx);
1704         W_ERROR_HAVE_NO_MEMORY(tmp_ctx);
1705
1706         name = dns_split_node_name(tmp_ctx, node_name, z->name);
1707         W_ERROR_HAVE_NO_MEMORY_AND_FREE(name, tmp_ctx);
1708
1709         if (add_buf != NULL) {
1710                 if (del_buf == NULL) {
1711                         /* Add record */
1712                         status = dnsserver_db_add_record(tmp_ctx, dsstate->samdb,
1713                                                                 z, name,
1714                                                                 &add_buf->rec);
1715                 } else {
1716                         /* Update record */
1717                         status = dnsserver_db_update_record(tmp_ctx, dsstate->samdb,
1718                                                                 z, name,
1719                                                                 &add_buf->rec,
1720                                                                 &del_buf->rec);
1721                 }
1722         } else {
1723                 if (del_buf == NULL) {
1724                         /* Add empty node */
1725                         status = dnsserver_db_add_empty_node(tmp_ctx, dsstate->samdb,
1726                                                                 z, name);
1727                 } else {
1728                         /* Delete record */
1729                         status = dnsserver_db_delete_record(tmp_ctx, dsstate->samdb,
1730                                                                 z, name,
1731                                                                 &del_buf->rec);
1732                 }
1733         }
1734
1735         talloc_free(tmp_ctx);
1736         return status;
1737 }
1738
1739
1740 /* dnsserver interface functions */
1741
1742 static WERROR dcesrv_DnssrvOperation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvOperation *r)
1743 {
1744         struct dnsserver_state *dsstate;
1745         struct dnsserver_zone *z = NULL;
1746         uint32_t request_filter = 0;
1747         WERROR ret;
1748
1749         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1750                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1751         }
1752
1753         if (r->in.dwContext == 0) {
1754                 if (r->in.pszZone != NULL) {
1755                         request_filter = dnsserver_zone_to_request_filter(r->in.pszZone);
1756                 }
1757         } else {
1758                 request_filter = r->in.dwContext;
1759         }
1760
1761         if (r->in.pszZone == NULL) {
1762                 ret = dnsserver_operate_server(dsstate, mem_ctx,
1763                                                 r->in.pszOperation,
1764                                                 DNS_CLIENT_VERSION_W2K,
1765                                                 r->in.dwTypeId,
1766                                                 &r->in.pData);
1767         } else {
1768                 ret = dnsserver_operate_zone(dsstate, mem_ctx, z,
1769                                                 request_filter,
1770                                                 r->in.pszOperation,
1771                                                 DNS_CLIENT_VERSION_W2K,
1772                                                 r->in.dwTypeId,
1773                                                 &r->in.pData);
1774         }
1775
1776         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1777                 NDR_PRINT_FUNCTION_DEBUG(DnssrvOperation, NDR_IN, r);
1778         }
1779         return ret;
1780 }
1781
1782 static WERROR dcesrv_DnssrvQuery(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvQuery *r)
1783 {
1784         struct dnsserver_state *dsstate;
1785         struct dnsserver_zone *z;
1786         WERROR ret;
1787
1788         ZERO_STRUCTP(r->out.pdwTypeId);
1789         ZERO_STRUCTP(r->out.ppData);
1790
1791         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1792                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1793         }
1794
1795         if (r->in.pszZone == NULL) {
1796                 /* FIXME: DNS Server Configuration Access Control List */
1797                 ret = dnsserver_query_server(dsstate, mem_ctx,
1798                                                 r->in.pszOperation,
1799                                                 DNS_CLIENT_VERSION_W2K,
1800                                                 r->out.pdwTypeId,
1801                                                 r->out.ppData);
1802         } else {
1803                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
1804                 if (z == NULL) {
1805                         return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
1806                 }
1807
1808                 ret = dnsserver_query_zone(dsstate, mem_ctx, z,
1809                                                 r->in.pszOperation,
1810                                                 DNS_CLIENT_VERSION_W2K,
1811                                                 r->out.pdwTypeId,
1812                                                 r->out.ppData);
1813         }
1814
1815         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1816                 NDR_PRINT_FUNCTION_DEBUG(DnssrvQuery, NDR_IN, r);
1817         }
1818         return ret;
1819 }
1820
1821 static WERROR dcesrv_DnssrvComplexOperation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvComplexOperation *r)
1822 {
1823         struct dnsserver_state *dsstate;
1824         struct dnsserver_zone *z;
1825         WERROR ret;
1826
1827         ZERO_STRUCTP(r->out.pdwTypeOut);
1828         ZERO_STRUCTP(r->out.ppDataOut);
1829
1830         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1831                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1832         }
1833
1834         if (r->in.pszZone == NULL) {
1835                 /* Server operation */
1836                 ret = dnsserver_complex_operate_server(dsstate, mem_ctx,
1837                                                         r->in.pszOperation,
1838                                                         DNS_CLIENT_VERSION_W2K,
1839                                                         r->in.dwTypeIn,
1840                                                         &r->in.pDataIn,
1841                                                         r->out.pdwTypeOut,
1842                                                         r->out.ppDataOut);
1843         } else {
1844                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
1845                 if (z == NULL) {
1846                         return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
1847                 }
1848
1849                 ret = dnsserver_complex_operate_zone(dsstate, mem_ctx, z,
1850                                                         r->in.pszOperation,
1851                                                         DNS_CLIENT_VERSION_W2K,
1852                                                         r->in.dwTypeIn,
1853                                                         &r->in.pDataIn,
1854                                                         r->out.pdwTypeOut,
1855                                                         r->out.ppDataOut);
1856         }
1857
1858         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1859                 NDR_PRINT_FUNCTION_DEBUG(DnssrvComplexOperation, NDR_IN, r);
1860         }
1861         return ret;
1862 }
1863
1864 static WERROR dcesrv_DnssrvEnumRecords(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvEnumRecords *r)
1865 {
1866         struct dnsserver_state *dsstate;
1867         struct dnsserver_zone *z;
1868         WERROR ret;
1869
1870         ZERO_STRUCTP(r->out.pdwBufferLength);
1871         ZERO_STRUCTP(r->out.pBuffer);
1872
1873         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1874                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1875         }
1876
1877         if (r->in.pszZone == NULL) {
1878                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1879         }
1880
1881         if (strcasecmp(r->in.pszZone, "..RootHints") == 0) {
1882                 ret = dnsserver_enumerate_root_records(dsstate, mem_ctx,
1883                                         DNS_CLIENT_VERSION_W2K,
1884                                         r->in.pszNodeName,
1885                                         r->in.wRecordType,
1886                                         r->in.fSelectFlag,
1887                                         r->out.pdwBufferLength,
1888                                         r->out.pBuffer);
1889         } else {
1890                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
1891                 if (z == NULL) {
1892                         return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1893                 }
1894
1895                 ret = dnsserver_enumerate_records(dsstate, mem_ctx, z,
1896                                         DNS_CLIENT_VERSION_W2K,
1897                                         r->in.pszNodeName,
1898                                         r->in.pszStartChild,
1899                                         r->in.wRecordType,
1900                                         r->in.fSelectFlag,
1901                                         r->in.pszFilterStart,
1902                                         r->in.pszFilterStop,
1903                                         r->out.pdwBufferLength,
1904                                         r->out.pBuffer);
1905         }
1906
1907         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1908                 NDR_PRINT_FUNCTION_DEBUG(DnssrvEnumRecords, NDR_IN, r);
1909         }
1910         return ret;
1911 }
1912
1913 static WERROR dcesrv_DnssrvUpdateRecord(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvUpdateRecord *r)
1914 {
1915         struct dnsserver_state *dsstate;
1916         struct dnsserver_zone *z;
1917         WERROR ret;
1918
1919         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1920                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1921         }
1922
1923         if (r->in.pszZone == NULL) {
1924                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1925         }
1926
1927         z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
1928         if (z == NULL) {
1929                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
1930         }
1931
1932         ret = dnsserver_update_record(dsstate, mem_ctx, z,
1933                                         DNS_CLIENT_VERSION_W2K,
1934                                         r->in.pszNodeName,
1935                                         r->in.pAddRecord,
1936                                         r->in.pDeleteRecord);
1937
1938         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1939                 NDR_PRINT_FUNCTION_DEBUG(DnssrvUpdateRecord, NDR_IN, r);
1940         }
1941         return ret;
1942 }
1943
1944 static WERROR dcesrv_DnssrvOperation2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvOperation2 *r)
1945 {
1946         struct dnsserver_state *dsstate;
1947         struct dnsserver_zone *z = NULL;
1948         uint32_t request_filter = 0;
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.dwContext == 0) {
1956                 if (r->in.pszZone != NULL) {
1957                         request_filter = dnsserver_zone_to_request_filter(r->in.pszZone);
1958                 }
1959         } else {
1960                 request_filter = r->in.dwContext;
1961         }
1962
1963         if (r->in.pszZone == NULL) {
1964                 ret = dnsserver_operate_server(dsstate, mem_ctx,
1965                                                 r->in.pszOperation,
1966                                                 r->in.dwClientVersion,
1967                                                 r->in.dwTypeId,
1968                                                 &r->in.pData);
1969         } else {
1970                 ret = dnsserver_operate_zone(dsstate, mem_ctx, z,
1971                                                 request_filter,
1972                                                 r->in.pszOperation,
1973                                                 r->in.dwClientVersion,
1974                                                 r->in.dwTypeId,
1975                                                 &r->in.pData);
1976         }
1977
1978         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
1979                 NDR_PRINT_FUNCTION_DEBUG(DnssrvOperation2, NDR_IN, r);
1980         }
1981         return ret;
1982 }
1983
1984 static WERROR dcesrv_DnssrvQuery2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvQuery2 *r)
1985 {
1986         struct dnsserver_state *dsstate;
1987         struct dnsserver_zone *z;
1988         WERROR ret;
1989
1990         ZERO_STRUCTP(r->out.pdwTypeId);
1991         ZERO_STRUCTP(r->out.ppData);
1992
1993         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
1994                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
1995         }
1996
1997         if (r->in.pszZone == NULL) {
1998                 /* FIXME: DNS Server Configuration Access Control List */
1999                 ret = dnsserver_query_server(dsstate, mem_ctx,
2000                                                 r->in.pszOperation,
2001                                                 r->in.dwClientVersion,
2002                                                 r->out.pdwTypeId,
2003                                                 r->out.ppData);
2004         } else {
2005                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
2006                 if (z == NULL) {
2007                         return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
2008                 }
2009
2010                 ret = dnsserver_query_zone(dsstate, mem_ctx, z,
2011                                         r->in.pszOperation,
2012                                         r->in.dwClientVersion,
2013                                         r->out.pdwTypeId,
2014                                         r->out.ppData);
2015         }
2016
2017         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2018                 NDR_PRINT_FUNCTION_DEBUG(DnssrvQuery2, NDR_IN, r);
2019         }
2020         return ret;
2021 }
2022
2023 static WERROR dcesrv_DnssrvComplexOperation2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvComplexOperation2 *r)
2024 {
2025         struct dnsserver_state *dsstate;
2026         struct dnsserver_zone *z;
2027         WERROR ret;
2028
2029         ZERO_STRUCTP(r->out.pdwTypeOut);
2030         ZERO_STRUCTP(r->out.ppDataOut);
2031
2032         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
2033                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
2034         }
2035
2036         if (r->in.pszZone == NULL) {
2037                 /* Server operation */
2038                 ret =  dnsserver_complex_operate_server(dsstate, mem_ctx,
2039                                                         r->in.pszOperation,
2040                                                         r->in.dwClientVersion,
2041                                                         r->in.dwTypeIn,
2042                                                         &r->in.pDataIn,
2043                                                         r->out.pdwTypeOut,
2044                                                         r->out.ppDataOut);
2045         } else {
2046
2047                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
2048                 if (z == NULL) {
2049                         return WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST;
2050                 }
2051
2052                 ret = dnsserver_complex_operate_zone(dsstate, mem_ctx, z,
2053                                                         r->in.pszOperation,
2054                                                         r->in.dwClientVersion,
2055                                                         r->in.dwTypeIn,
2056                                                         &r->in.pDataIn,
2057                                                         r->out.pdwTypeOut,
2058                                                         r->out.ppDataOut);
2059         }
2060
2061         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2062                 NDR_PRINT_FUNCTION_DEBUG(DnssrvComplexOperation2, NDR_IN, r);
2063         }
2064         return ret;
2065 }
2066
2067 static WERROR dcesrv_DnssrvEnumRecords2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvEnumRecords2 *r)
2068 {
2069         struct dnsserver_state *dsstate;
2070         struct dnsserver_zone *z;
2071         WERROR ret;
2072
2073         ZERO_STRUCTP(r->out.pdwBufferLength);
2074         ZERO_STRUCTP(r->out.pBuffer);
2075
2076         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
2077                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
2078         }
2079
2080         if (r->in.pszZone == NULL) {
2081                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2082         }
2083
2084         if (strcasecmp(r->in.pszZone, "..RootHints") == 0) {
2085                 ret =  dnsserver_enumerate_root_records(dsstate, mem_ctx,
2086                                         r->in.dwClientVersion,
2087                                         r->in.pszNodeName,
2088                                         r->in.wRecordType,
2089                                         r->in.fSelectFlag,
2090                                         r->out.pdwBufferLength,
2091                                         r->out.pBuffer);
2092         } else {
2093                 z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
2094                 if (z == NULL) {
2095                         return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2096                 }
2097
2098                 ret =  dnsserver_enumerate_records(dsstate, mem_ctx, z,
2099                                         r->in.dwClientVersion,
2100                                         r->in.pszNodeName,
2101                                         r->in.pszStartChild,
2102                                         r->in.wRecordType,
2103                                         r->in.fSelectFlag,
2104                                         r->in.pszFilterStart,
2105                                         r->in.pszFilterStop,
2106                                         r->out.pdwBufferLength,
2107                                         r->out.pBuffer);
2108
2109         }
2110
2111         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2112                 NDR_PRINT_FUNCTION_DEBUG(DnssrvEnumRecords2, NDR_IN, r);
2113         }
2114         return ret;
2115 }
2116
2117 static WERROR dcesrv_DnssrvUpdateRecord2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct DnssrvUpdateRecord2 *r)
2118 {
2119         struct dnsserver_state *dsstate;
2120         struct dnsserver_zone *z;
2121         WERROR ret;
2122
2123         if ((dsstate = dnsserver_connect(dce_call)) == NULL) {
2124                 return WERR_DNS_ERROR_DS_UNAVAILABLE;
2125         }
2126
2127         if (r->in.pszZone == NULL) {
2128                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2129         }
2130
2131         z = dnsserver_find_zone(dsstate->zones, r->in.pszZone);
2132         if (z == NULL) {
2133                 return WERR_DNS_ERROR_NAME_DOES_NOT_EXIST;
2134         }
2135
2136         ret = dnsserver_update_record(dsstate, mem_ctx, z,
2137                                         r->in.dwClientVersion,
2138                                         r->in.pszNodeName,
2139                                         r->in.pAddRecord,
2140                                         r->in.pDeleteRecord);
2141
2142         if (W_ERROR_EQUAL(ret, WERR_CALL_NOT_IMPLEMENTED)) {
2143                 NDR_PRINT_FUNCTION_DEBUG(DnssrvUpdateRecord2, NDR_IN, r);
2144         }
2145         return ret;
2146 }
2147
2148 /* include the generated boilerplate */
2149 #include "librpc/gen_ndr/ndr_dnsserver_s.c"