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