3 # Copyright (C) Amitay Isaacs 2011-2012
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 import samba.getopt as options
20 from samba import WERRORError
21 from samba import werror
22 from struct import pack
23 from socket import inet_ntoa
24 from socket import inet_ntop
25 from socket import AF_INET
26 from socket import AF_INET6
29 from samba.netcmd import (
35 from samba.dcerpc import dnsp, dnsserver
38 def dns_connect(server, lp, creds):
39 if server.lower() == 'localhost':
41 binding_str = "ncacn_ip_tcp:%s[sign]" % server
43 dns_conn = dnsserver.dnsserver(binding_str, lp, creds)
44 except RuntimeError, e:
45 raise CommandError('Connecting to DNS RPC server %s failed with %s' % (server, e))
50 def bool_string(flag):
56 ret = 'UNKNOWN (0x%x)' % flag
60 def enum_string(module, enum_defs, value):
63 if value == getattr(module, e):
67 ret = 'UNKNOWN (0x%x)' % value
71 def bitmap_string(module, bitmap_defs, value):
74 if value & getattr(module, b):
81 def boot_method_string(boot_method):
82 enum_defs = [ 'DNS_BOOT_METHOD_UNINITIALIZED', 'DNS_BOOT_METHOD_FILE',
83 'DNS_BOOT_METHOD_REGISTRY', 'DNS_BOOT_METHOD_DIRECTORY' ]
84 return enum_string(dnsserver, enum_defs, boot_method)
87 def name_check_flag_string(check_flag):
88 enum_defs = [ 'DNS_ALLOW_RFC_NAMES_ONLY', 'DNS_ALLOW_NONRFC_NAMES',
89 'DNS_ALLOW_MULTIBYTE_NAMES', 'DNS_ALLOW_ALL_NAMES' ]
90 return enum_string(dnsserver, enum_defs, check_flag)
93 def zone_type_string(zone_type):
94 enum_defs = [ 'DNS_ZONE_TYPE_CACHE', 'DNS_ZONE_TYPE_PRIMARY',
95 'DNS_ZONE_TYPE_SECONDARY', 'DNS_ZONE_TYPE_STUB',
96 'DNS_ZONE_TYPE_FORWARDER', 'DNS_ZONE_TYPE_SECONDARY_CACHE' ]
97 return enum_string(dnsp, enum_defs, zone_type)
100 def zone_update_string(zone_update):
101 enum_defs = [ 'DNS_ZONE_UPDATE_OFF', 'DNS_ZONE_UPDATE_UNSECURE',
102 'DNS_ZONE_UPDATE_SECURE' ]
103 return enum_string(dnsp, enum_defs, zone_update)
106 def zone_secondary_security_string(security):
107 enum_defs = [ 'DNS_ZONE_SECSECURE_NO_SECURITY', 'DNS_ZONE_SECSECURE_NS_ONLY',
108 'DNS_ZONE_SECSECURE_LIST_ONLY', 'DNS_ZONE_SECSECURE_NO_XFER' ]
109 return enum_string(dnsserver, enum_defs, security)
112 def zone_notify_level_string(notify_level):
113 enum_defs = [ 'DNS_ZONE_NOTIFY_OFF', 'DNS_ZONE_NOTIFY_ALL_SECONDARIES',
114 'DNS_ZONE_NOTIFY_LIST_ONLY' ]
115 return enum_string(dnsserver, enum_defs, notify_level)
118 def dp_flags_string(dp_flags):
119 bitmap_defs = [ 'DNS_DP_AUTOCREATED', 'DNS_DP_LEGACY', 'DNS_DP_DOMAIN_DEFAULT',
120 'DNS_DP_FOREST_DEFAULT', 'DNS_DP_ENLISTED', 'DNS_DP_DELETED' ]
121 return bitmap_string(dnsserver, bitmap_defs, dp_flags)
124 def zone_flags_string(flags):
125 bitmap_defs = [ 'DNS_RPC_ZONE_PAUSED', 'DNS_RPC_ZONE_SHUTDOWN',
126 'DNS_RPC_ZONE_REVERSE', 'DNS_RPC_ZONE_AUTOCREATED',
127 'DNS_RPC_ZONE_DSINTEGRATED', 'DNS_RPC_ZONE_AGING',
128 'DNS_RPC_ZONE_UPDATE_UNSECURE', 'DNS_RPC_ZONE_UPDATE_SECURE',
129 'DNS_RPC_ZONE_READONLY']
130 return bitmap_string(dnsserver, bitmap_defs, flags)
133 def ip4_array_string(array):
137 for i in xrange(array.AddrCount):
138 addr = inet_ntop(AF_INET, pack('I', array.AddrArray[i]))
143 def dns_addr_array_string(array):
147 for i in xrange(array.AddrCount):
148 if array.AddrArray[i].MaxSa[0] == 0x02:
149 x = "".join([chr(b) for b in array.AddrArray[i].MaxSa])[4:8]
150 addr = inet_ntop(AF_INET, x)
151 elif array.AddrArray[i].MaxSa[0] == 0x17:
152 x = "".join([chr(b) for b in array.AddrArray[i].MaxSa])[8:24]
153 addr = inet_ntop(AF_INET6, x)
160 def dns_type_flag(rec_type):
161 rtype = rec_type.upper()
163 record_type = dnsp.DNS_TYPE_A
164 elif rtype == 'AAAA':
165 record_type = dnsp.DNS_TYPE_AAAA
167 record_type = dnsp.DNS_TYPE_PTR
169 record_type = dnsp.DNS_TYPE_NS
170 elif rtype == 'CNAME':
171 record_type = dnsp.DNS_TYPE_CNAME
173 record_type = dnsp.DNS_TYPE_SOA
175 record_type = dnsp.DNS_TYPE_MX
177 record_type = dnsp.DNS_TYPE_SRV
179 record_type = dnsp.DNS_TYPE_TXT
181 record_type = dnsp.DNS_TYPE_ALL
183 raise CommandError('Unknown type of DNS record %s' % rec_type)
187 def dns_client_version(cli_version):
188 version = cli_version.upper()
190 client_version = dnsserver.DNS_CLIENT_VERSION_W2K
191 elif version == 'DOTNET':
192 client_version = dnsserver.DNS_CLIENT_VERSION_DOTNET
193 elif version == 'LONGHORN':
194 client_version = dnsserver.DNS_CLIENT_VERSION_LONGHORN
196 raise CommandError('Unknown client version %s' % cli_version)
197 return client_version
200 def print_serverinfo(outf, typeid, serverinfo):
201 outf.write(' dwVersion : 0x%x\n' % serverinfo.dwVersion)
202 outf.write(' fBootMethod : %s\n' % boot_method_string(serverinfo.fBootMethod))
203 outf.write(' fAdminConfigured : %s\n' % bool_string(serverinfo.fAdminConfigured))
204 outf.write(' fAllowUpdate : %s\n' % bool_string(serverinfo.fAllowUpdate))
205 outf.write(' fDsAvailable : %s\n' % bool_string(serverinfo.fDsAvailable))
206 outf.write(' pszServerName : %s\n' % serverinfo.pszServerName)
207 outf.write(' pszDsContainer : %s\n' % serverinfo.pszDsContainer)
209 if typeid != dnsserver.DNSSRV_TYPEID_SERVER_INFO:
210 outf.write(' aipServerAddrs : %s\n' %
211 ip4_array_string(serverinfo.aipServerAddrs))
212 outf.write(' aipListenAddrs : %s\n' %
213 ip4_array_string(serverinfo.aipListenAddrs))
214 outf.write(' aipForwarders : %s\n' %
215 ip4_array_string(serverinfo.aipForwarders))
217 outf.write(' aipServerAddrs : %s\n' %
218 dns_addr_array_string(serverinfo.aipServerAddrs))
219 outf.write(' aipListenAddrs : %s\n' %
220 dns_addr_array_string(serverinfo.aipListenAddrs))
221 outf.write(' aipForwarders : %s\n' %
222 dns_addr_array_string(serverinfo.aipForwarders))
224 outf.write(' dwLogLevel : %d\n' % serverinfo.dwLogLevel)
225 outf.write(' dwDebugLevel : %d\n' % serverinfo.dwDebugLevel)
226 outf.write(' dwForwardTimeout : %d\n' % serverinfo.dwForwardTimeout)
227 outf.write(' dwRpcPrototol : 0x%x\n' % serverinfo.dwRpcProtocol)
228 outf.write(' dwNameCheckFlag : %s\n' % name_check_flag_string(serverinfo.dwNameCheckFlag))
229 outf.write(' cAddressAnswerLimit : %d\n' % serverinfo.cAddressAnswerLimit)
230 outf.write(' dwRecursionRetry : %d\n' % serverinfo.dwRecursionRetry)
231 outf.write(' dwRecursionTimeout : %d\n' % serverinfo.dwRecursionTimeout)
232 outf.write(' dwMaxCacheTtl : %d\n' % serverinfo.dwMaxCacheTtl)
233 outf.write(' dwDsPollingInterval : %d\n' % serverinfo.dwDsPollingInterval)
234 outf.write(' dwScavengingInterval : %d\n' % serverinfo.dwScavengingInterval)
235 outf.write(' dwDefaultRefreshInterval : %d\n' % serverinfo.dwDefaultRefreshInterval)
236 outf.write(' dwDefaultNoRefreshInterval : %d\n' % serverinfo.dwDefaultNoRefreshInterval)
237 outf.write(' fAutoReverseZones : %s\n' % bool_string(serverinfo.fAutoReverseZones))
238 outf.write(' fAutoCacheUpdate : %s\n' % bool_string(serverinfo.fAutoCacheUpdate))
239 outf.write(' fRecurseAfterForwarding : %s\n' % bool_string(serverinfo.fRecurseAfterForwarding))
240 outf.write(' fForwardDelegations : %s\n' % bool_string(serverinfo.fForwardDelegations))
241 outf.write(' fNoRecursion : %s\n' % bool_string(serverinfo.fNoRecursion))
242 outf.write(' fSecureResponses : %s\n' % bool_string(serverinfo.fSecureResponses))
243 outf.write(' fRoundRobin : %s\n' % bool_string(serverinfo.fRoundRobin))
244 outf.write(' fLocalNetPriority : %s\n' % bool_string(serverinfo.fLocalNetPriority))
245 outf.write(' fBindSecondaries : %s\n' % bool_string(serverinfo.fBindSecondaries))
246 outf.write(' fWriteAuthorityNs : %s\n' % bool_string(serverinfo.fWriteAuthorityNs))
247 outf.write(' fStrictFileParsing : %s\n' % bool_string(serverinfo.fStrictFileParsing))
248 outf.write(' fLooseWildcarding : %s\n' % bool_string(serverinfo.fLooseWildcarding))
249 outf.write(' fDefaultAgingState : %s\n' % bool_string(serverinfo.fDefaultAgingState))
251 if typeid != dnsserver.DNSSRV_TYPEID_SERVER_INFO_W2K:
252 outf.write(' dwRpcStructureVersion : 0x%x\n' % serverinfo.dwRpcStructureVersion)
253 outf.write(' aipLogFilter : %s\n' % dns_addr_array_string(serverinfo.aipLogFilter))
254 outf.write(' pwszLogFilePath : %s\n' % serverinfo.pwszLogFilePath)
255 outf.write(' pszDomainName : %s\n' % serverinfo.pszDomainName)
256 outf.write(' pszForestName : %s\n' % serverinfo.pszForestName)
257 outf.write(' pszDomainDirectoryPartition : %s\n' % serverinfo.pszDomainDirectoryPartition)
258 outf.write(' pszForestDirectoryPartition : %s\n' % serverinfo.pszForestDirectoryPartition)
260 outf.write(' dwLocalNetPriorityNetMask : 0x%x\n' % serverinfo.dwLocalNetPriorityNetMask)
261 outf.write(' dwLastScavengeTime : %d\n' % serverinfo.dwLastScavengeTime)
262 outf.write(' dwEventLogLevel : %d\n' % serverinfo.dwEventLogLevel)
263 outf.write(' dwLogFileMaxSize : %d\n' % serverinfo.dwLogFileMaxSize)
264 outf.write(' dwDsForestVersion : %d\n' % serverinfo.dwDsForestVersion)
265 outf.write(' dwDsDomainVersion : %d\n' % serverinfo.dwDsDomainVersion)
266 outf.write(' dwDsDsaVersion : %d\n' % serverinfo.dwDsDsaVersion)
268 if typeid == dnsserver.DNSSRV_TYPEID_SERVER_INFO:
269 outf.write(' fReadOnlyDC : %s\n' % bool_string(serverinfo.fReadOnlyDC))
272 def print_zoneinfo(outf, typeid, zoneinfo):
273 outf.write(' pszZoneName : %s\n' % zoneinfo.pszZoneName)
274 outf.write(' dwZoneType : %s\n' % zone_type_string(zoneinfo.dwZoneType))
275 outf.write(' fReverse : %s\n' % bool_string(zoneinfo.fReverse))
276 outf.write(' fAllowUpdate : %s\n' % zone_update_string(zoneinfo.fAllowUpdate))
277 outf.write(' fPaused : %s\n' % bool_string(zoneinfo.fPaused))
278 outf.write(' fShutdown : %s\n' % bool_string(zoneinfo.fShutdown))
279 outf.write(' fAutoCreated : %s\n' % bool_string(zoneinfo.fAutoCreated))
280 outf.write(' fUseDatabase : %s\n' % bool_string(zoneinfo.fUseDatabase))
281 outf.write(' pszDataFile : %s\n' % zoneinfo.pszDataFile)
282 if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
283 outf.write(' aipMasters : %s\n' %
284 ip4_array_string(zoneinfo.aipMasters))
286 outf.write(' aipMasters : %s\n' %
287 dns_addr_array_string(zoneinfo.aipMasters))
288 outf.write(' fSecureSecondaries : %s\n' % zone_secondary_security_string(zoneinfo.fSecureSecondaries))
289 outf.write(' fNotifyLevel : %s\n' % zone_notify_level_string(zoneinfo.fNotifyLevel))
290 if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
291 outf.write(' aipSecondaries : %s\n' %
292 ip4_array_string(zoneinfo.aipSecondaries))
293 outf.write(' aipNotify : %s\n' %
294 ip4_array_string(zoneinfo.aipNotify))
296 outf.write(' aipSecondaries : %s\n' %
297 dns_addr_array_string(zoneinfo.aipSecondaries))
298 outf.write(' aipNotify : %s\n' %
299 dns_addr_array_string(zoneinfo.aipNotify))
300 outf.write(' fUseWins : %s\n' % bool_string(zoneinfo.fUseWins))
301 outf.write(' fUseNbstat : %s\n' % bool_string(zoneinfo.fUseNbstat))
302 outf.write(' fAging : %s\n' % bool_string(zoneinfo.fAging))
303 outf.write(' dwNoRefreshInterval : %d\n' % zoneinfo.dwNoRefreshInterval)
304 outf.write(' dwRefreshInterval : %d\n' % zoneinfo.dwRefreshInterval)
305 outf.write(' dwAvailForScavengeTime : %d\n' % zoneinfo.dwAvailForScavengeTime)
306 if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
307 outf.write(' aipScavengeServers : %s\n' %
308 ip4_array_string(zoneinfo.aipScavengeServers))
310 outf.write(' aipScavengeServers : %s\n' %
311 dns_addr_array_string(zoneinfo.aipScavengeServers))
313 if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO_W2K:
314 outf.write(' dwRpcStructureVersion : 0x%x\n' % zoneinfo.dwRpcStructureVersion)
315 outf.write(' dwForwarderTimeout : %d\n' % zoneinfo.dwForwarderTimeout)
316 outf.write(' fForwarderSlave : %d\n' % zoneinfo.fForwarderSlave)
317 if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
318 outf.write(' aipLocalMasters : %s\n' %
319 ip4_array_string(zoneinfo.aipLocalMasters))
321 outf.write(' aipLocalMasters : %s\n' %
322 dns_addr_array_string(zoneinfo.aipLocalMasters))
323 outf.write(' dwDpFlags : %s\n' % dp_flags_string(zoneinfo.dwDpFlags))
324 outf.write(' pszDpFqdn : %s\n' % zoneinfo.pszDpFqdn)
325 outf.write(' pwszZoneDn : %s\n' % zoneinfo.pwszZoneDn)
326 outf.write(' dwLastSuccessfulSoaCheck : %d\n' % zoneinfo.dwLastSuccessfulSoaCheck)
327 outf.write(' dwLastSuccessfulXfr : %d\n' % zoneinfo.dwLastSuccessfulXfr)
329 if typeid == dnsserver.DNSSRV_TYPEID_ZONE_INFO:
330 outf.write(' fQueuedForBackgroundLoad : %s\n' % bool_string(zoneinfo.fQueuedForBackgroundLoad))
331 outf.write(' fBackgroundLoadInProgress : %s\n' % bool_string(zoneinfo.fBackgroundLoadInProgress))
332 outf.write(' fReadOnlyZone : %s\n' % bool_string(zoneinfo.fReadOnlyZone))
333 outf.write(' dwLastXfrAttempt : %d\n' % zoneinfo.dwLastXfrAttempt)
334 outf.write(' dwLastXfrResult : %d\n' % zoneinfo.dwLastXfrResult)
337 def print_zone(outf, typeid, zone):
338 outf.write(' pszZoneName : %s\n' % zone.pszZoneName)
339 outf.write(' Flags : %s\n' % zone_flags_string(zone.Flags))
340 outf.write(' ZoneType : %s\n' % zone_type_string(zone.ZoneType))
341 outf.write(' Version : %s\n' % zone.Version)
343 if typeid != dnsserver.DNSSRV_TYPEID_ZONE_W2K:
344 outf.write(' dwDpFlags : %s\n' % dp_flags_string(zone.dwDpFlags))
345 outf.write(' pszDpFqdn : %s\n' % zone.pszDpFqdn)
348 def print_enumzones(outf, typeid, zones):
349 outf.write(' %d zone(s) found\n' % zones.dwZoneCount)
350 for zone in zones.ZoneArray:
352 print_zone(outf, typeid, zone)
355 def print_dns_record(outf, rec):
356 if rec.wType == dnsp.DNS_TYPE_A:
357 mesg = 'A: %s' % (rec.data)
358 elif rec.wType == dnsp.DNS_TYPE_AAAA:
359 mesg = 'AAAA: %s' % (rec.data)
360 elif rec.wType == dnsp.DNS_TYPE_PTR:
361 mesg = 'PTR: %s' % (rec.data.str)
362 elif rec.wType == dnsp.DNS_TYPE_NS:
363 mesg = 'NS: %s' % (rec.data.str)
364 elif rec.wType == dnsp.DNS_TYPE_CNAME:
365 mesg = 'CNAME: %s' % (rec.data.str)
366 elif rec.wType == dnsp.DNS_TYPE_SOA:
367 mesg = 'SOA: serial=%d, refresh=%d, retry=%d, expire=%d, minttl=%d, ns=%s, email=%s' % (
372 rec.data.dwMinimumTtl,
373 rec.data.NamePrimaryServer.str,
374 rec.data.ZoneAdministratorEmail.str)
375 elif rec.wType == dnsp.DNS_TYPE_MX:
376 mesg = 'MX: %s (%d)' % (rec.data.nameExchange.str, rec.data.wPreference)
377 elif rec.wType == dnsp.DNS_TYPE_SRV:
378 mesg = 'SRV: %s (%d, %d, %d)' % (rec.data.nameTarget.str, rec.data.wPort,
379 rec.data.wPriority, rec.data.wWeight)
380 elif rec.wType == dnsp.DNS_TYPE_TXT:
381 slist = ['"%s"' % name.str for name in rec.data.str]
382 mesg = 'TXT: %s' % ','.join(slist)
385 outf.write(' %s (flags=%x, serial=%d, ttl=%d)\n' % (
386 mesg, rec.dwFlags, rec.dwSerial, rec.dwTtlSeconds))
389 def print_dnsrecords(outf, records):
390 for rec in records.rec:
391 outf.write(' Name=%s, Records=%d, Children=%d\n' % (
395 for dns_rec in rec.records:
396 print_dns_record(outf, dns_rec)
400 # Always create a copy of strings when creating DNS_RPC_RECORDs
401 # to overcome the bug in pidl generated python bindings.
404 class ARecord(dnsserver.DNS_RPC_RECORD):
405 def __init__(self, ip_addr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
407 super(ARecord, self).__init__()
408 self.wType = dnsp.DNS_TYPE_A
409 self.dwFlags = rank | node_flag
410 self.dwSerial = serial
411 self.dwTtlSeconds = ttl
412 self._ip_addr = ip_addr[:]
413 self.data = self._ip_addr
416 class AAAARecord(dnsserver.DNS_RPC_RECORD):
418 def __init__(self, ip6_addr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
420 super(AAAARecord, self).__init__()
421 self.wType = dnsp.DNS_TYPE_AAAA
422 self.dwFlags = rank | node_flag
423 self.dwSerial = serial
424 self.dwTtlSeconds = ttl
425 self._ip6_addr = ip6_addr[:]
426 self.data = self._ip6_addr
429 class PTRRecord(dnsserver.DNS_RPC_RECORD):
431 def __init__(self, ptr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
433 super(PTRRecord, self).__init__()
434 self.wType = dnsp.DNS_TYPE_PTR
435 self.dwFlags = rank | node_flag
436 self.dwSerial = serial
437 self.dwTtlSeconds = ttl
439 ptr_name = dnsserver.DNS_RPC_NAME()
440 ptr_name.str = self._ptr
441 ptr_name.len = len(ptr)
445 class CNameRecord(dnsserver.DNS_RPC_RECORD):
447 def __init__(self, cname, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
449 super(CNameRecord, self).__init__()
450 self.wType = dnsp.DNS_TYPE_CNAME
451 self.dwFlags = rank | node_flag
452 self.dwSerial = serial
453 self.dwTtlSeconds = ttl
454 self._cname = cname[:]
455 cname_name = dnsserver.DNS_RPC_NAME()
456 cname_name.str = self._cname
457 cname_name.len = len(cname)
458 self.data = cname_name
461 class NSRecord(dnsserver.DNS_RPC_RECORD):
463 def __init__(self, dns_server, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
465 super(NSRecord, self).__init__()
466 self.wType = dnsp.DNS_TYPE_NS
467 self.dwFlags = rank | node_flag
468 self.dwSerial = serial
469 self.dwTtlSeconds = ttl
470 self._dns_server = dns_server[:]
471 ns = dnsserver.DNS_RPC_NAME()
472 ns.str = self._dns_server
473 ns.len = len(dns_server)
477 class MXRecord(dnsserver.DNS_RPC_RECORD):
479 def __init__(self, mail_server, preference, serial=1, ttl=900,
480 rank=dnsp.DNS_RANK_ZONE, node_flag=0):
481 super(MXRecord, self).__init__()
482 self.wType = dnsp.DNS_TYPE_MX
483 self.dwFlags = rank | node_flag
484 self.dwSerial = serial
485 self.dwTtlSeconds = ttl
486 self._mail_server = mail_server[:]
487 mx = dnsserver.DNS_RPC_RECORD_NAME_PREFERENCE()
488 mx.wPreference = preference
489 mx.nameExchange.str = self._mail_server
490 mx.nameExchange.len = len(mail_server)
494 class SOARecord(dnsserver.DNS_RPC_RECORD):
496 def __init__(self, mname, rname, serial=1, refresh=900, retry=600,
497 expire=86400, minimum=3600, ttl=3600, rank=dnsp.DNS_RANK_ZONE,
498 node_flag=dnsp.DNS_RPC_FLAG_AUTH_ZONE_ROOT):
499 super(SOARecord, self).__init__()
500 self.wType = dnsp.DNS_TYPE_SOA
501 self.dwFlags = rank | node_flag
502 self.dwSerial = serial
503 self.dwTtlSeconds = ttl
504 self._mname = mname[:]
505 self._rname = rname[:]
506 soa = dnsserver.DNS_RPC_RECORD_SOA()
507 soa.dwSerialNo = serial
508 soa.dwRefresh = refresh
510 soa.dwExpire = expire
511 soa.dwMinimumTtl = minimum
512 soa.NamePrimaryServer.str = self._mname
513 soa.NamePrimaryServer.len = len(mname)
514 soa.ZoneAdministratorEmail.str = self._rname
515 soa.ZoneAdministratorEmail.len = len(rname)
519 class SRVRecord(dnsserver.DNS_RPC_RECORD):
521 def __init__(self, target, port, priority=0, weight=100, serial=1, ttl=900,
522 rank=dnsp.DNS_RANK_ZONE, node_flag=0):
523 super(SRVRecord, self).__init__()
524 self.wType = dnsp.DNS_TYPE_SRV
525 self.dwFlags = rank | node_flag
526 self.dwSerial = serial
527 self.dwTtlSeconds = ttl
528 self._target = target[:]
529 srv = dnsserver.DNS_RPC_RECORD_SRV()
530 srv.wPriority = priority
533 srv.nameTarget.str = self._target
534 srv.nameTarget.len = len(target)
538 class TXTRecord(dnsserver.DNS_RPC_RECORD):
540 def __init__(self, slist, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
542 super(TXTRecord, self).__init__()
543 self.wType = dnsp.DNS_TYPE_TXT
544 self.dwFlags = rank | node_flag
545 self.dwSerial = serial
546 self.dwTtlSeconds = ttl
549 self._slist.append(s[:])
551 for s in self._slist:
552 name = dnsserver.DNS_RPC_NAME()
556 txt = dnsserver.DNS_RPC_RECORD_STRING()
557 txt.count = len(slist)
562 # Convert data into a dns record
563 def data_to_dns_record(record_type, data):
564 if record_type == dnsp.DNS_TYPE_A:
566 elif record_type == dnsp.DNS_TYPE_AAAA:
567 rec = AAAARecord(data)
568 elif record_type == dnsp.DNS_TYPE_PTR:
569 rec = PTRRecord(data)
570 elif record_type == dnsp.DNS_TYPE_CNAME:
571 rec = CNameRecord(data)
572 elif record_type == dnsp.DNS_TYPE_NS:
574 elif record_type == dnsp.DNS_TYPE_MX:
575 tmp = data.split(' ')
577 raise CommandError('Data requires 2 elements - mail_server, preference')
579 preference = int(tmp[1])
580 rec = MXRecord(mail_server, preference)
581 elif record_type == dnsp.DNS_TYPE_SRV:
582 tmp = data.split(' ')
584 raise CommandError('Data requires 4 elements - server, port, priority, weight')
587 priority = int(tmp[2])
589 rec = SRVRecord(server, port, priority=priority, weight=weight)
590 elif record_type == dnsp.DNS_TYPE_SOA:
591 tmp = data.split(' ')
593 raise CommandError('Data requires 7 elements - nameserver, email, serial, '
594 'refresh, retry, expire, minimumttl')
598 refresh = int(tmp[3])
601 minimum = int(tmp[6])
602 rec = SOARecord(nameserver, email, serial=serial, refresh=refresh,
603 retry=retry, expire=expire, minimum=minimum)
604 elif record_type == dnsp.DNS_TYPE_TXT:
605 slist = shlex.split(data)
606 rec = TXTRecord(slist)
608 raise CommandError('Unsupported record type')
612 # Match dns name (of type DNS_RPC_NAME)
613 def dns_name_equal(n1, n2):
614 return n1.str.rstrip('.').lower() == n2.str.rstrip('.').lower()
617 # Match a dns record with specified data
618 def dns_record_match(dns_conn, server, zone, name, record_type, data):
619 urec = data_to_dns_record(record_type, data)
621 select_flags = dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
624 buflen, res = dns_conn.DnssrvEnumRecords2(
625 dnsserver.DNS_CLIENT_VERSION_LONGHORN, 0, server, zone, name, None,
626 record_type, select_flags, None, None)
627 except WERRORError as e:
628 if e.args[0] == werror.WERR_DNS_ERROR_NAME_DOES_NOT_EXIST:
629 # Either the zone doesn't exist, or there were no records.
630 # We can't differentiate the two.
634 if not res or res.count == 0:
637 for rec in res.rec[0].records:
638 if rec.wType != record_type:
642 if record_type == dnsp.DNS_TYPE_A:
643 if rec.data == urec.data:
645 elif record_type == dnsp.DNS_TYPE_AAAA:
646 if rec.data == urec.data:
648 elif record_type == dnsp.DNS_TYPE_PTR:
649 if dns_name_equal(rec.data, urec.data):
651 elif record_type == dnsp.DNS_TYPE_CNAME:
652 if dns_name_equal(rec.data, urec.data):
654 elif record_type == dnsp.DNS_TYPE_NS:
655 if dns_name_equal(rec.data, urec.data):
657 elif record_type == dnsp.DNS_TYPE_MX:
658 if dns_name_equal(rec.data.nameExchange, urec.data.nameExchange) and \
659 rec.data.wPreference == urec.data.wPreference:
661 elif record_type == dnsp.DNS_TYPE_SRV:
662 if rec.data.wPriority == urec.data.wPriority and \
663 rec.data.wWeight == urec.data.wWeight and \
664 rec.data.wPort == urec.data.wPort and \
665 dns_name_equal(rec.data.nameTarget, urec.data.nameTarget):
667 elif record_type == dnsp.DNS_TYPE_SOA:
668 if rec.data.dwSerialNo == urec.data.dwSerialNo and \
669 rec.data.dwRefresh == urec.data.dwRefresh and \
670 rec.data.dwRetry == urec.data.dwRetry and \
671 rec.data.dwExpire == urec.data.dwExpire and \
672 rec.data.dwMinimumTtl == urec.data.dwMinimumTtl and \
673 dns_name_equal(rec.data.NamePrimaryServer,
674 urec.data.NamePrimaryServer) and \
675 dns_name_equal(rec.data.ZoneAdministratorEmail,
676 urec.data.ZoneAdministratorEmail):
678 elif record_type == dnsp.DNS_TYPE_TXT:
679 if rec.data.count == urec.data.count:
681 for i in xrange(rec.data.count):
683 (rec.data.str[i].str == urec.data.str[i].str)
691 class cmd_serverinfo(Command):
692 """Query for Server information."""
694 synopsis = '%prog <server> [options]'
696 takes_args = [ 'server' ]
698 takes_optiongroups = {
699 "sambaopts": options.SambaOptions,
700 "versionopts": options.VersionOptions,
701 "credopts": options.CredentialsOptions,
705 Option('--client-version', help='Client Version',
706 default='longhorn', metavar='w2k|dotnet|longhorn',
707 choices=['w2k','dotnet','longhorn'], dest='cli_ver'),
710 def run(self, server, cli_ver, sambaopts=None, credopts=None,
712 self.lp = sambaopts.get_loadparm()
713 self.creds = credopts.get_credentials(self.lp)
714 dns_conn = dns_connect(server, self.lp, self.creds)
716 client_version = dns_client_version(cli_ver)
718 typeid, res = dns_conn.DnssrvQuery2(client_version, 0, server,
720 print_serverinfo(self.outf, typeid, res)
723 class cmd_zoneinfo(Command):
724 """Query for zone information."""
726 synopsis = '%prog <server> <zone> [options]'
728 takes_args = [ 'server', 'zone' ]
730 takes_optiongroups = {
731 "sambaopts": options.SambaOptions,
732 "versionopts": options.VersionOptions,
733 "credopts": options.CredentialsOptions,
737 Option('--client-version', help='Client Version',
738 default='longhorn', metavar='w2k|dotnet|longhorn',
739 choices=['w2k','dotnet','longhorn'], dest='cli_ver'),
742 def run(self, server, zone, cli_ver, sambaopts=None, credopts=None,
744 self.lp = sambaopts.get_loadparm()
745 self.creds = credopts.get_credentials(self.lp)
746 dns_conn = dns_connect(server, self.lp, self.creds)
748 client_version = dns_client_version(cli_ver)
750 typeid, res = dns_conn.DnssrvQuery2(client_version, 0, server, zone,
752 print_zoneinfo(self.outf, typeid, res)
755 class cmd_zonelist(Command):
756 """Query for zones."""
758 synopsis = '%prog <server> [options]'
760 takes_args = [ 'server' ]
762 takes_optiongroups = {
763 "sambaopts": options.SambaOptions,
764 "versionopts": options.VersionOptions,
765 "credopts": options.CredentialsOptions,
769 Option('--client-version', help='Client Version',
770 default='longhorn', metavar='w2k|dotnet|longhorn',
771 choices=['w2k','dotnet','longhorn'], dest='cli_ver'),
772 Option('--primary', help='List primary zones (default)',
773 action='store_true', dest='primary'),
774 Option('--secondary', help='List secondary zones',
775 action='store_true', dest='secondary'),
776 Option('--cache', help='List cached zones',
777 action='store_true', dest='cache'),
778 Option('--auto', help='List automatically created zones',
779 action='store_true', dest='auto'),
780 Option('--forward', help='List forward zones',
781 action='store_true', dest='forward'),
782 Option('--reverse', help='List reverse zones',
783 action='store_true', dest='reverse'),
784 Option('--ds', help='List directory integrated zones',
785 action='store_true', dest='ds'),
786 Option('--non-ds', help='List non-directory zones',
787 action='store_true', dest='nonds')
790 def run(self, server, cli_ver, primary=False, secondary=False, cache=False,
791 auto=False, forward=False, reverse=False, ds=False, nonds=False,
792 sambaopts=None, credopts=None, versionopts=None):
796 request_filter |= dnsserver.DNS_ZONE_REQUEST_PRIMARY
798 request_filter |= dnsserver.DNS_ZONE_REQUEST_SECONDARY
800 request_filter |= dnsserver.DNS_ZONE_REQUEST_CACHE
802 request_filter |= dnsserver.DNS_ZONE_REQUEST_AUTO
804 request_filter |= dnsserver.DNS_ZONE_REQUEST_FORWARD
806 request_filter |= dnsserver.DNS_ZONE_REQUEST_REVERSE
808 request_filter |= dnsserver.DNS_ZONE_REQUEST_DS
810 request_filter |= dnsserver.DNS_ZONE_REQUEST_NON_DS
812 if request_filter == 0:
813 request_filter = dnsserver.DNS_ZONE_REQUEST_PRIMARY
815 self.lp = sambaopts.get_loadparm()
816 self.creds = credopts.get_credentials(self.lp)
817 dns_conn = dns_connect(server, self.lp, self.creds)
819 client_version = dns_client_version(cli_ver)
821 typeid, res = dns_conn.DnssrvComplexOperation2(client_version,
824 dnsserver.DNSSRV_TYPEID_DWORD,
827 if client_version == dnsserver.DNS_CLIENT_VERSION_W2K:
828 typeid = dnsserver.DNSSRV_TYPEID_ZONE_W2K
830 typeid = dnsserver.DNSSRV_TYPEID_ZONE
831 print_enumzones(self.outf, typeid, res)
834 class cmd_zonecreate(Command):
837 synopsis = '%prog <server> <zone> [options]'
839 takes_args = [ 'server', 'zone' ]
841 takes_optiongroups = {
842 "sambaopts": options.SambaOptions,
843 "versionopts": options.VersionOptions,
844 "credopts": options.CredentialsOptions,
848 Option('--client-version', help='Client Version',
849 default='longhorn', metavar='w2k|dotnet|longhorn',
850 choices=['w2k','dotnet','longhorn'], dest='cli_ver')
853 def run(self, server, zone, cli_ver, sambaopts=None, credopts=None,
856 self.lp = sambaopts.get_loadparm()
857 self.creds = credopts.get_credentials(self.lp)
858 dns_conn = dns_connect(server, self.lp, self.creds)
862 client_version = dns_client_version(cli_ver)
863 if client_version == dnsserver.DNS_CLIENT_VERSION_W2K:
864 typeid = dnsserver.DNSSRV_TYPEID_ZONE_CREATE_W2K
865 zone_create_info = dnsserver.DNS_RPC_ZONE_CREATE_INFO_W2K()
866 zone_create_info.pszZoneName = zone
867 zone_create_info.dwZoneType = dnsp.DNS_ZONE_TYPE_PRIMARY
868 zone_create_info.fAging = 0
869 zone_create_info.fDsIntegrated = 1
870 zone_create_info.fLoadExisting = 1
871 elif client_version == dnsserver.DNS_CLIENT_VERSION_DOTNET:
872 typeid = dnsserver.DNSSRV_TYPEID_ZONE_CREATE_DOTNET
873 zone_create_info = dnsserver.DNS_RPC_ZONE_CREATE_INFO_DOTNET()
874 zone_create_info.pszZoneName = zone
875 zone_create_info.dwZoneType = dnsp.DNS_ZONE_TYPE_PRIMARY
876 zone_create_info.fAging = 0
877 zone_create_info.fDsIntegrated = 1
878 zone_create_info.fLoadExisting = 1
879 zone_create_info.dwDpFlags = dnsserver.DNS_DP_DOMAIN_DEFAULT
881 typeid = dnsserver.DNSSRV_TYPEID_ZONE_CREATE
882 zone_create_info = dnsserver.DNS_RPC_ZONE_CREATE_INFO_LONGHORN()
883 zone_create_info.pszZoneName = zone
884 zone_create_info.dwZoneType = dnsp.DNS_ZONE_TYPE_PRIMARY
885 zone_create_info.fAging = 0
886 zone_create_info.fDsIntegrated = 1
887 zone_create_info.fLoadExisting = 1
888 zone_create_info.dwDpFlags = dnsserver.DNS_DP_DOMAIN_DEFAULT
890 res = dns_conn.DnssrvOperation2(client_version, 0, server, None,
891 0, 'ZoneCreate', typeid,
894 typeid = dnsserver.DNSSRV_TYPEID_NAME_AND_PARAM
895 name_and_param = dnsserver.DNS_RPC_NAME_AND_PARAM()
896 name_and_param.pszNodeName = 'AllowUpdate'
897 name_and_param.dwParam = dnsp.DNS_ZONE_UPDATE_SECURE
900 res = dns_conn.DnssrvOperation2(client_version, 0, server, zone,
901 0, 'ResetDwordProperty', typeid,
903 except WERRORError as e:
904 if e.args[0] == werror.WERR_DNS_ERROR_ZONE_ALREADY_EXISTS:
905 self.outf.write('Zone already exists.')
908 self.outf.write('Zone %s created successfully\n' % zone)
911 class cmd_zonedelete(Command):
914 synopsis = '%prog <server> <zone> [options]'
916 takes_args = [ 'server', 'zone' ]
918 takes_optiongroups = {
919 "sambaopts": options.SambaOptions,
920 "versionopts": options.VersionOptions,
921 "credopts": options.CredentialsOptions,
924 def run(self, server, zone, sambaopts=None, credopts=None,
927 self.lp = sambaopts.get_loadparm()
928 self.creds = credopts.get_credentials(self.lp)
929 dns_conn = dns_connect(server, self.lp, self.creds)
933 res = dns_conn.DnssrvOperation2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
934 0, server, zone, 0, 'DeleteZoneFromDs',
935 dnsserver.DNSSRV_TYPEID_NULL,
937 except WERRORError as e:
938 if e.args[0] == werror.WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST:
939 self.outf.write('Zone does not exist and so could not be deleted.')
942 self.outf.write('Zone %s deleted successfully\n' % zone)
945 class cmd_query(Command):
948 synopsis = '%prog <server> <zone> <name> <A|AAAA|CNAME|MX|NS|SOA|SRV|TXT|ALL> [options]'
950 takes_args = [ 'server', 'zone', 'name', 'rtype' ]
952 takes_optiongroups = {
953 "sambaopts": options.SambaOptions,
954 "versionopts": options.VersionOptions,
955 "credopts": options.CredentialsOptions,
959 Option('--authority', help='Search authoritative records (default)',
960 action='store_true', dest='authority'),
961 Option('--cache', help='Search cached records',
962 action='store_true', dest='cache'),
963 Option('--glue', help='Search glue records',
964 action='store_true', dest='glue'),
965 Option('--root', help='Search root hints',
966 action='store_true', dest='root'),
967 Option('--additional', help='List additional records',
968 action='store_true', dest='additional'),
969 Option('--no-children', help='Do not list children',
970 action='store_true', dest='no_children'),
971 Option('--only-children', help='List only children',
972 action='store_true', dest='only_children')
975 def run(self, server, zone, name, rtype, authority=False, cache=False,
976 glue=False, root=False, additional=False, no_children=False,
977 only_children=False, sambaopts=None, credopts=None,
979 record_type = dns_type_flag(rtype)
981 if name.find('*') != -1:
982 raise CommandError('Wildcard searches not supported. To dump entire zone use "@"')
986 select_flags |= dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
988 select_flags |= dnsserver.DNS_RPC_VIEW_CACHE_DATA
990 select_flags |= dnsserver.DNS_RPC_VIEW_GLUE_DATA
992 select_flags |= dnsserver.DNS_RPC_VIEW_ROOT_HINT_DATA
994 select_flags |= dnsserver.DNS_RPC_VIEW_ADDITIONAL_DATA
996 select_flags |= dnsserver.DNS_RPC_VIEW_NO_CHILDREN
998 select_flags |= dnsserver.DNS_RPC_VIEW_ONLY_CHILDREN
1000 if select_flags == 0:
1001 select_flags = dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
1003 if select_flags == dnsserver.DNS_RPC_VIEW_ADDITIONAL_DATA:
1004 self.outf.write('Specify either --authority or --root along with --additional.\n')
1005 self.outf.write('Assuming --authority.\n')
1006 select_flags |= dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
1008 self.lp = sambaopts.get_loadparm()
1009 self.creds = credopts.get_credentials(self.lp)
1010 dns_conn = dns_connect(server, self.lp, self.creds)
1013 buflen, res = dns_conn.DnssrvEnumRecords2(
1014 dnsserver.DNS_CLIENT_VERSION_LONGHORN, 0, server, zone, name,
1015 None, record_type, select_flags, None, None)
1016 except WERRORError as e:
1017 if e.args[0] == werror.WERR_DNS_ERROR_NAME_DOES_NOT_EXIST:
1018 self.outf.write('Record or zone does not exist.')
1021 print_dnsrecords(self.outf, res)
1024 class cmd_roothints(Command):
1025 """Query root hints."""
1027 synopsis = '%prog <server> [<name>] [options]'
1029 takes_args = [ 'server', 'name?' ]
1031 takes_optiongroups = {
1032 "sambaopts": options.SambaOptions,
1033 "versionopts": options.VersionOptions,
1034 "credopts": options.CredentialsOptions,
1037 def run(self, server, name='.', sambaopts=None, credopts=None,
1039 record_type = dnsp.DNS_TYPE_NS
1040 select_flags = (dnsserver.DNS_RPC_VIEW_ROOT_HINT_DATA |
1041 dnsserver.DNS_RPC_VIEW_ADDITIONAL_DATA)
1043 self.lp = sambaopts.get_loadparm()
1044 self.creds = credopts.get_credentials(self.lp)
1045 dns_conn = dns_connect(server, self.lp, self.creds)
1047 buflen, res = dns_conn.DnssrvEnumRecords2(
1048 dnsserver.DNS_CLIENT_VERSION_LONGHORN, 0, server, '..RootHints',
1049 name, None, record_type, select_flags, None, None)
1050 print_dnsrecords(self.outf, res)
1053 class cmd_add_record(Command):
1056 For each type data contents are as follows:
1057 A ipv4_address_string
1058 AAAA ipv6_address_string
1062 MX "fqdn_string preference"
1063 SRV "fqdn_string port priority weight"
1064 TXT "'string1' 'string2' ..."
1067 synopsis = '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SRV|TXT> <data>'
1069 takes_args = [ 'server', 'zone', 'name', 'rtype', 'data' ]
1071 takes_optiongroups = {
1072 "sambaopts": options.SambaOptions,
1073 "versionopts": options.VersionOptions,
1074 "credopts": options.CredentialsOptions,
1077 def run(self, server, zone, name, rtype, data, sambaopts=None,
1078 credopts=None, versionopts=None):
1080 if rtype.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SRV','TXT'):
1081 raise CommandError('Adding record of type %s is not supported' % rtype)
1083 record_type = dns_type_flag(rtype)
1084 rec = data_to_dns_record(record_type, data)
1086 self.lp = sambaopts.get_loadparm()
1087 self.creds = credopts.get_credentials(self.lp)
1088 dns_conn = dns_connect(server, self.lp, self.creds)
1090 add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
1091 add_rec_buf.rec = rec
1094 dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
1095 0, server, zone, name, add_rec_buf, None)
1096 except WERRORError as e:
1097 if e.args[0] == werror.WERR_DNS_ERROR_NAME_DOES_NOT_EXIST:
1098 self.outf.write('Zone does not exist; record could not be added.\n')
1101 self.outf.write('Record added successfully\n')
1104 class cmd_update_record(Command):
1105 """Update a DNS record
1107 For each type data contents are as follows:
1108 A ipv4_address_string
1109 AAAA ipv6_address_string
1113 MX "fqdn_string preference"
1114 SOA "fqdn_dns fqdn_email serial refresh retry expire minimumttl"
1115 SRV "fqdn_string port priority weight"
1116 TXT "'string1' 'string2' ..."
1119 synopsis = '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SOA|SRV|TXT> <olddata> <newdata>'
1121 takes_args = [ 'server', 'zone', 'name', 'rtype', 'olddata', 'newdata' ]
1123 takes_optiongroups = {
1124 "sambaopts": options.SambaOptions,
1125 "versionopts": options.VersionOptions,
1126 "credopts": options.CredentialsOptions,
1129 def run(self, server, zone, name, rtype, olddata, newdata,
1130 sambaopts=None, credopts=None, versionopts=None):
1132 if rtype.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SOA','SRV','TXT'):
1133 raise CommandError('Updating record of type %s is not supported' % rtype)
1135 record_type = dns_type_flag(rtype)
1136 rec = data_to_dns_record(record_type, newdata)
1138 self.lp = sambaopts.get_loadparm()
1139 self.creds = credopts.get_credentials(self.lp)
1140 dns_conn = dns_connect(server, self.lp, self.creds)
1142 rec_match = dns_record_match(dns_conn, server, zone, name, record_type,
1145 raise CommandError('Record or zone does not exist.')
1147 # Copy properties from existing record to new record
1148 rec.dwFlags = rec_match.dwFlags
1149 rec.dwSerial = rec_match.dwSerial
1150 rec.dwTtlSeconds = rec_match.dwTtlSeconds
1151 rec.dwTimeStamp = rec_match.dwTimeStamp
1153 add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
1154 add_rec_buf.rec = rec
1156 del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
1157 del_rec_buf.rec = rec_match
1160 dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
1167 except WERRORError as e:
1168 if e.args[0] == werror.WERR_DNS_ERROR_NAME_DOES_NOT_EXIST:
1169 self.outf.write('Zone does not exist; record could not be updated.\n')
1172 self.outf.write('Record updated successfully\n')
1175 class cmd_delete_record(Command):
1176 """Delete a DNS record
1178 For each type data contents are as follows:
1179 A ipv4_address_string
1180 AAAA ipv6_address_string
1184 MX "fqdn_string preference"
1185 SRV "fqdn_string port priority weight"
1186 TXT "'string1' 'string2' ..."
1189 synopsis = '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SRV|TXT> <data>'
1191 takes_args = [ 'server', 'zone', 'name', 'rtype', 'data' ]
1193 takes_optiongroups = {
1194 "sambaopts": options.SambaOptions,
1195 "versionopts": options.VersionOptions,
1196 "credopts": options.CredentialsOptions,
1199 def run(self, server, zone, name, rtype, data, sambaopts=None, credopts=None, versionopts=None):
1201 if rtype.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SRV','TXT'):
1202 raise CommandError('Deleting record of type %s is not supported' % rtype)
1204 record_type = dns_type_flag(rtype)
1205 rec = data_to_dns_record(record_type, data)
1207 self.lp = sambaopts.get_loadparm()
1208 self.creds = credopts.get_credentials(self.lp)
1209 dns_conn = dns_connect(server, self.lp, self.creds)
1211 del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
1212 del_rec_buf.rec = rec
1215 dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
1222 except WERRORError as e:
1223 if e.args[0] == werror.WERR_DNS_ERROR_NAME_DOES_NOT_EXIST:
1224 self.outf.write('Zone does not exist; record could not be deleted.\n')
1227 self.outf.write('Record deleted successfully\n')
1230 class cmd_dns(SuperCommand):
1231 """Domain Name Service (DNS) management."""
1234 subcommands['serverinfo'] = cmd_serverinfo()
1235 subcommands['zoneinfo'] = cmd_zoneinfo()
1236 subcommands['zonelist'] = cmd_zonelist()
1237 subcommands['zonecreate'] = cmd_zonecreate()
1238 subcommands['zonedelete'] = cmd_zonedelete()
1239 subcommands['query'] = cmd_query()
1240 subcommands['roothints'] = cmd_roothints()
1241 subcommands['add'] = cmd_add_record()
1242 subcommands['update'] = cmd_update_record()
1243 subcommands['delete'] = cmd_delete_record()