5 # Copyright (C) Amitay Isaacs 2011
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 import samba.getopt as options
24 from struct import pack
25 from socket import inet_ntoa
27 from samba.netcmd import (
33 from samba.dcerpc import dnsp, dnsserver
34 from samba.ndr import ndr_print
37 def dns_connect(server, lp, creds):
38 binding_str = "ncacn_ip_tcp:%s[sign]" % server
39 dns_conn = dnsserver.dnsserver(binding_str, lp, creds)
42 def bool_string(flag):
48 ret = 'UNKNOWN (0x%x)' % flag
51 def enum_string(module, enum_defs, value):
54 if value == getattr(module, e):
58 ret = 'UNKNOWN (0x%x)' % value
61 def bitmap_string(module, bitmap_defs, value):
64 if value & getattr(module, b):
70 def boot_method_string(boot_method):
71 enum_defs = [ 'DNS_BOOT_METHOD_UNINITIALIZED', 'DNS_BOOT_METHOD_FILE',
72 'DNS_BOOT_METHOD_REGISTRY', 'DNS_BOOT_METHOD_DIRECTORY' ]
73 return enum_string(dnsserver, enum_defs, boot_method)
75 def name_check_flag_string(check_flag):
76 enum_defs = [ 'DNS_ALLOW_RFC_NAMES_ONLY', 'DNS_ALLOW_NONRFC_NAMES',
77 'DNS_ALLOW_MULTIBYTE_NAMES', 'DNS_ALLOW_ALL_NAMES' ]
78 return enum_string(dnsserver, enum_defs, check_flag)
80 def zone_type_string(zone_type):
81 enum_defs = [ 'DNS_ZONE_TYPE_CACHE', 'DNS_ZONE_TYPE_PRIMARY',
82 'DNS_ZONE_TYPE_SECONDARY', 'DNS_ZONE_TYPE_STUB',
83 'DNS_ZONE_TYPE_FORWARDER', 'DNS_ZONE_TYPE_SECONDARY_CACHE' ]
84 return enum_string(dnsp, enum_defs, zone_type)
86 def zone_update_string(zone_update):
87 enum_defs = [ 'DNS_ZONE_UPDATE_OFF', 'DNS_ZONE_UPDATE_SECURE',
88 'DNS_ZONE_UPDATE_SECURE' ]
89 return enum_string(dnsp, enum_defs, zone_update)
91 def zone_secondary_security_string(security):
92 enum_defs = [ 'DNS_ZONE_SECSECURE_NO_SECURITY', 'DNS_ZONE_SECSECURE_NS_ONLY',
93 'DNS_ZONE_SECSECURE_LIST_ONLY', 'DNS_ZONE_SECSECURE_NO_XFER' ]
94 return enum_string(dnsserver, enum_defs, security)
96 def zone_notify_level_string(notify_level):
97 enum_defs = [ 'DNS_ZONE_NOTIFY_OFF', 'DNS_ZONE_NOTIFY_ALL_SECONDARIES',
98 'DNS_ZONE_NOTIFY_LIST_ONLY' ]
99 return enum_string(dnsserver, enum_defs, notify_level)
101 def dp_flags_string(dp_flags):
102 bitmap_defs = [ 'DNS_DP_AUTOCREATED', 'DNS_DP_LEGACY', 'DNS_DP_DOMAIN_DEFAULT',
103 'DNS_DP_FOREST_DEFAULT', 'DNS_DP_ENLISTED', 'DNS_DP_DELETED' ]
104 return bitmap_string(dnsserver, bitmap_defs, dp_flags)
106 def zone_flags_string(flags):
107 bitmap_defs = [ 'DNS_RPC_ZONE_PAUSED', 'DNS_RPC_ZONE_SHUTDOWN',
108 'DNS_RPC_ZONE_REVERSE', 'DNS_RPC_ZONE_AUTOCREATED',
109 'DNS_RPC_ZONE_DSINTEGRATED', 'DNS_RPC_ZONE_AGING',
110 'DNS_RPC_ZONE_UPDATE_UNSECURE', 'DNS_RPC_ZONE_UPDATE_SECURE',
111 'DNS_RPC_ZONE_READONLY']
112 return bitmap_string(dnsserver, bitmap_defs, flags)
114 def ip4_array_string(array):
118 for i in xrange(array.AddrCount):
119 addr = '%s' % inet_ntoa(pack('i', array.AddrArray[i]))
123 def dns_addr_array_string(array):
127 for i in xrange(array.AddrCount):
128 if array.AddrArray[i].MaxSa[0] == 0x02:
129 addr = '%d.%d.%d.%d (%d)' % \
130 tuple(array.AddrArray[i].MaxSa[4:8] + [array.AddrArray[i].MaxSa[3]])
131 elif array.AddrArray[i].MaxSa[0] == 0x17:
132 addr = '%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x (%d)' % \
133 tuple(array.AddrArray[i].MaxSa[4:20] + [array.AddrArray[i].MaxSa[3]])
139 def dns_type_flag(rec_type):
140 rtype = rec_type.upper()
142 record_type = dnsp.DNS_TYPE_A
144 record_type = dnsp.DNS_TYPE_NS
145 elif rtype == 'CNAME':
146 record_type = dnsp.DNS_TYPE_CNAME
148 record_type = dnsp.DNS_TYPE_SOA
150 record_type = dnsp.DNS_TYPE_MX
152 record_type = dnsp.DNS_TYPE_SRV
154 record_type = dnsp.DNS_TYPE_ALL
156 raise CommandError('Unknown type of DNS record %s' % rec_type)
159 def dns_client_version(cli_version):
160 version = cli_version.upper()
162 client_version = dnsserver.DNS_CLIENT_VERSION_W2K
163 elif version == 'DOTNET':
164 client_version = dnsserver.DNS_CLIENT_VERSION_DOTNET
165 elif version == 'LONGHORN':
166 client_version = dnsserver.DNS_CLIENT_VERSION_LONGHORN
168 raise CommandError('Unknown client version %s' % cli_version)
169 return client_version
171 def print_serverinfo(outf, typeid, serverinfo):
172 outf.write(' dwVersion : 0x%x\n' % serverinfo.dwVersion)
173 outf.write(' fBootMethod : %s\n' % boot_method_string(serverinfo.fBootMethod))
174 outf.write(' fAdminConfigured : %s\n' % bool_string(serverinfo.fAdminConfigured))
175 outf.write(' fAllowUpdate : %s\n' % bool_string(serverinfo.fAllowUpdate))
176 outf.write(' fDsAvailable : %s\n' % bool_string(serverinfo.fDsAvailable))
177 outf.write(' pszServerName : %s\n' % serverinfo.pszServerName)
178 outf.write(' pszDsContainer : %s\n' % serverinfo.pszDsContainer)
180 if typeid != dnsserver.DNSSRV_TYPEID_SERVER_INFO:
181 outf.write(' aipServerAddrs : %s\n' %
182 ip4_array_string(serverinfo.aipServerAddrs))
183 outf.write(' aipListenAddrs : %s\n' %
184 ip4_array_string(serverinfo.aipListenAddrs))
185 outf.write(' aipForwarders : %s\n' %
186 ip4_array_string(serverinfo.aipForwarders))
188 outf.write(' aipServerAddrs : %s\n' %
189 dns_addr_array_string(serverinfo.aipServerAddrs))
190 outf.write(' aipListenAddrs : %s\n' %
191 dns_addr_array_string(serverinfo.aipListenAddrs))
192 outf.write(' aipForwarders : %s\n' %
193 dns_addr_array_string(serverinfo.aipForwarders))
195 outf.write(' dwLogLevel : %d\n' % serverinfo.dwLogLevel)
196 outf.write(' dwDebugLevel : %d\n' % serverinfo.dwDebugLevel)
197 outf.write(' dwForwardTimeout : %d\n' % serverinfo.dwForwardTimeout)
198 outf.write(' dwRpcPrototol : 0x%x\n' % serverinfo.dwRpcProtocol)
199 outf.write(' dwNameCheckFlag : %s\n' % name_check_flag_string(serverinfo.dwNameCheckFlag))
200 outf.write(' cAddressAnswerLimit : %d\n' % serverinfo.cAddressAnswerLimit)
201 outf.write(' dwRecursionRetry : %d\n' % serverinfo.dwRecursionRetry)
202 outf.write(' dwRecursionTimeout : %d\n' % serverinfo.dwRecursionTimeout)
203 outf.write(' dwMaxCacheTtl : %d\n' % serverinfo.dwMaxCacheTtl)
204 outf.write(' dwDsPollingInterval : %d\n' % serverinfo.dwDsPollingInterval)
205 outf.write(' dwScavengingInterval : %d\n' % serverinfo.dwScavengingInterval)
206 outf.write(' dwDefaultRefreshInterval : %d\n' % serverinfo.dwDefaultRefreshInterval)
207 outf.write(' dwDefaultNoRefreshInterval : %d\n' % serverinfo.dwDefaultNoRefreshInterval)
208 outf.write(' fAutoReverseZones : %s\n' % bool_string(serverinfo.fAutoReverseZones))
209 outf.write(' fAutoCacheUpdate : %s\n' % bool_string(serverinfo.fAutoCacheUpdate))
210 outf.write(' fRecurseAfterForwarding : %s\n' % bool_string(serverinfo.fRecurseAfterForwarding))
211 outf.write(' fForwardDelegations : %s\n' % bool_string(serverinfo.fForwardDelegations))
212 outf.write(' fNoRecursion : %s\n' % bool_string(serverinfo.fNoRecursion))
213 outf.write(' fSecureResponses : %s\n' % bool_string(serverinfo.fSecureResponses))
214 outf.write(' fRoundRobin : %s\n' % bool_string(serverinfo.fRoundRobin))
215 outf.write(' fLocalNetPriority : %s\n' % bool_string(serverinfo.fLocalNetPriority))
216 outf.write(' fBindSecondaries : %s\n' % bool_string(serverinfo.fBindSecondaries))
217 outf.write(' fWriteAuthorityNs : %s\n' % bool_string(serverinfo.fWriteAuthorityNs))
218 outf.write(' fStrictFileParsing : %s\n' % bool_string(serverinfo.fStrictFileParsing))
219 outf.write(' fLooseWildcarding : %s\n' % bool_string(serverinfo.fLooseWildcarding))
220 outf.write(' fDefaultAgingState : %s\n' % bool_string(serverinfo.fDefaultAgingState))
222 if typeid != dnsserver.DNSSRV_TYPEID_SERVER_INFO_W2K:
223 outf.write(' dwRpcStructureVersion : 0x%x\n' % serverinfo.dwRpcStructureVersion)
224 outf.write(' aipLogFilter : %s\n' % dns_addr_array_string(serverinfo.aipLogFilter))
225 outf.write(' pwszLogFilePath : %s\n' % serverinfo.pwszLogFilePath)
226 outf.write(' pszDomainName : %s\n' % serverinfo.pszDomainName)
227 outf.write(' pszForestName : %s\n' % serverinfo.pszForestName)
228 outf.write(' pszDomainDirectoryPartition : %s\n' % serverinfo.pszDomainDirectoryPartition)
229 outf.write(' pszForestDirectoryPartition : %s\n' % serverinfo.pszForestDirectoryPartition)
231 outf.write(' dwLocalNetPriorityNetMask : 0x%x\n' % serverinfo.dwLocalNetPriorityNetMask)
232 outf.write(' dwLastScavengeTime : %d\n' % serverinfo.dwLastScavengeTime)
233 outf.write(' dwEventLogLevel : %d\n' % serverinfo.dwEventLogLevel)
234 outf.write(' dwLogFileMaxSize : %d\n' % serverinfo.dwLogFileMaxSize)
235 outf.write(' dwDsForestVersion : %d\n' % serverinfo.dwDsForestVersion)
236 outf.write(' dwDsDomainVersion : %d\n' % serverinfo.dwDsDomainVersion)
237 outf.write(' dwDsDsaVersion : %d\n' % serverinfo.dwDsDsaVersion)
239 if typeid == dnsserver.DNSSRV_TYPEID_SERVER_INFO:
240 outf.write(' fReadOnlyDC : %s\n' % bool_string(serverinfo.fReadOnlyDC))
243 def print_zoneinfo(outf, typeid, zoneinfo):
244 outf.write(' pszZoneName : %s\n' % zoneinfo.pszZoneName)
245 outf.write(' dwZoneType : %s\n' % zone_type_string(zoneinfo.dwZoneType))
246 outf.write(' fReverse : %s\n' % bool_string(zoneinfo.fReverse))
247 outf.write(' fAllowUpdate : %s\n' % zone_update_string(zoneinfo.fAllowUpdate))
248 outf.write(' fPaused : %s\n' % bool_string(zoneinfo.fPaused))
249 outf.write(' fShutdown : %s\n' % bool_string(zoneinfo.fShutdown))
250 outf.write(' fAutoCreated : %s\n' % bool_string(zoneinfo.fAutoCreated))
251 outf.write(' fUseDatabase : %s\n' % bool_string(zoneinfo.fUseDatabase))
252 outf.write(' pszDataFile : %s\n' % zoneinfo.pszDataFile)
253 if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
254 outf.write(' aipMasters : %s\n' %
255 ip4_array_string(zoneinfo.aipMasters))
257 outf.write(' aipMasters : %s\n' %
258 dns_addr_array_string(zoneinfo.aipMasters))
259 outf.write(' fSecureSecondaries : %s\n' % zone_secondary_security_string(zoneinfo.fSecureSecondaries))
260 outf.write(' fNotifyLevel : %s\n' % zone_notify_level_string(zoneinfo.fNotifyLevel))
261 if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
262 outf.write(' aipSecondaries : %s\n' %
263 ip4_array_string(zoneinfo.aipSecondaries))
264 outf.write(' aipNotify : %s\n' %
265 ip4_array_string(zoneinfo.aipNotify))
267 outf.write(' aipSecondaries : %s\n' %
268 dns_addr_array_string(zoneinfo.aipSecondaries))
269 outf.write(' aipNotify : %s\n' %
270 dns_addr_array_string(zoneinfo.aipNotify))
271 outf.write(' fUseWins : %s\n' % bool_string(zoneinfo.fUseWins))
272 outf.write(' fUseNbstat : %s\n' % bool_string(zoneinfo.fUseNbstat))
273 outf.write(' fAging : %s\n' % bool_string(zoneinfo.fAging))
274 outf.write(' dwNoRefreshInterval : %d\n' % zoneinfo.dwNoRefreshInterval)
275 outf.write(' dwRefreshInterval : %d\n' % zoneinfo.dwRefreshInterval)
276 outf.write(' dwAvailForScavengeTime : %d\n' % zoneinfo.dwAvailForScavengeTime)
277 if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
278 outf.write(' aipScavengeServers : %s\n' %
279 ip4_array_string(zoneinfo.aipScavengeServers))
281 outf.write(' aipScavengeServers : %s\n' %
282 dns_addr_array_string(zoneinfo.aipScavengeServers))
284 if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO_W2K:
285 outf.write(' dwRpcStructureVersion : 0x%x\n' % zoneinfo.dwRpcStructureVersion)
286 outf.write(' dwForwarderTimeout : %d\n' % zoneinfo.dwForwarderTimeout)
287 outf.write(' fForwarderSlave : %d\n' % zoneinfo.fForwarderSlave)
288 if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
289 outf.write(' aipLocalMasters : %s\n' %
290 ip4_array_string(zoneinfo.aipLocalMasters))
292 outf.write(' aipLocalMasters : %s\n' %
293 dns_addr_array_string(zoneinfo.aipLocalMasters))
294 outf.write(' dwDpFlags : %s\n' % dp_flags_string(zoneinfo.dwDpFlags))
295 outf.write(' pszDpFqdn : %s\n' % zoneinfo.pszDpFqdn)
296 outf.write(' pwszZoneDn : %s\n' % zoneinfo.pwszZoneDn)
297 outf.write(' dwLastSuccessfulSoaCheck : %d\n' % zoneinfo.dwLastSuccessfulSoaCheck)
298 outf.write(' dwLastSuccessfulXfr : %d\n' % zoneinfo.dwLastSuccessfulXfr)
300 if typeid == dnsserver.DNSSRV_TYPEID_ZONE_INFO:
301 outf.write(' fQueuedForBackgroundLoad : %s\n' % bool_string(zoneinfo.fQueuedForBackgroundLoad))
302 outf.write(' fBackgroundLoadInProgress : %s\n' % bool_string(zoneinfo.fBackgroundLoadInProgress))
303 outf.write(' fReadOnlyZone : %s\n' % bool_string(zoneinfo.fReadOnlyZone))
304 outf.write(' dwLastXfrAttempt : %d\n' % zoneinfo.dwLastXfrAttempt)
305 outf.write(' dwLastXfrResult : %d\n' % zoneinfo.dwLastXfrResult)
308 def print_zone(outf, typeid, zone):
309 outf.write(' pszZoneName : %s\n' % zone.pszZoneName)
310 outf.write(' Flags : %s\n' % zone_flags_string(zone.Flags))
311 outf.write(' ZoneType : %s\n' % zone_type_string(zone.ZoneType))
312 outf.write(' Version : %s\n' % zone.Version)
314 if typeid != dnsserver.DNSSRV_TYPEID_ZONE_W2K:
315 outf.write(' dwDpFlags : %s\n' % dp_flags_string(zone.dwDpFlags))
316 outf.write(' pszDpFqdn : %s\n' % zone.pszDpFqdn)
319 def print_enumzones(outf, typeid, zones):
320 outf.write(' %d zone(s) found\n' % zones.dwZoneCount)
321 for zone in zones.ZoneArray:
323 print_zone(outf, typeid, zone)
326 def print_dns_record(outf, rec):
328 if rec.wType == dnsp.DNS_TYPE_A:
329 mesg = 'A: %s' % (rec.data)
330 elif rec.wType == dnsp.DNS_TYPE_NS:
331 mesg = 'NS: %s' % (rec.data.str)
332 elif rec.wType == dnsp.DNS_TYPE_CNAME:
333 mesg = 'CNAME: %s' % (rec.data.str)
334 elif rec.wType == dnsp.DNS_TYPE_SOA:
335 mesg = 'SOA: serial=%d, refresh=%d, retry=%d, expire=%d, ns=%s, email=%s' % (
340 rec.data.NamePrimaryServer.str,
341 rec.data.ZoneAdministratorEmail.str)
342 elif rec.wType == dnsp.DNS_TYPE_MX:
343 mesg = 'MX: %s' % (rec.data.str)
344 elif rec.wType == dnsp.DNS_TYPE_SRV:
345 mesg = 'SRV: %s (%d)' % (rec.data.nameTarget.str, rec.data.wPort)
346 outf.write(' %s (flags=%x, serial=%d, ttl=%d)\n' % (
347 mesg, rec.dwFlags, rec.dwSerial, rec.dwTtlSeconds))
350 def print_dnsrecords(outf, records):
351 for rec in records.rec:
352 outf.write(' Name=%s, Records=%d, Children=%d\n' % (
356 for dns_rec in rec.records:
357 print_dns_record(outf, dns_rec)
360 class ARecord(dnsserver.DNS_RPC_RECORD):
361 def __init__(self, ip_addr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
363 super(ARecord, self).__init__()
364 self.wType = dnsp.DNS_TYPE_A
365 self.dwFlags = rank | node_flag
366 self.dwSerial = serial
367 self.dwTtlSeconds = ttl
370 class AAAARecord(dnsserver.DNS_RPC_RECORD):
371 def __init__(self, ip6_addr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
373 super(AAAARecord, self).__init__()
374 self.wType = dnsp.DNS_TYPE_AAAA
375 self.dwFlags = rank | node_flag
376 self.dwSerial = serial
377 self.dwTtlSeconds = ttl
380 class CNameRecord(dnsserver.DNS_RPC_RECORD):
381 def __init__(self, cname, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
383 super(CNameRecord, self).__init__()
384 self.wType = dnsp.DNS_TYPE_CNAME
385 self.dwFlags = rank | node_flag
386 self.dwSerial = serial
387 self.dwTtlSeconds = ttl
388 cname_name = dnsserver.DNS_RPC_NAME()
389 cname_name.str = cname
390 cname_name.len = len(cname)
391 self.data = cname_name
393 class NSRecord(dnsserver.DNS_RPC_RECORD):
394 def __init__(self, dns_server, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
396 super(NSRecord, self).__init__()
397 self.wType = dnsp.DNS_TYPE_NS
398 self.dwFlags = rank | node_flag
399 self.dwSerial = serial
400 self.dwTtlSeconds = ttl
401 ns = dnsserver.DNS_RPC_NAME()
403 ns.len = len(dns_server)
406 class SOARecord(dnsserver.DNS_RPC_RECORD):
407 def __init__(self, mname, rname, serial=1, refresh=900, retry=600,
408 expire=86400, minimum=3600, ttl=3600, rank=dnsp.DNS_RANK_ZONE,
409 node_flag=dnsp.DNS_RPC_FLAG_AUTH_ZONE_ROOT):
410 super(SOARecord, self).__init__()
411 self.wType = dnsp.DNS_TYPE_SOA
412 self.dwFlags = rank | node_flag
413 self.dwSerial = serial
414 self.dwTtlSeconds = ttl
415 soa = dnsserver.DNS_RPC_RECORD_SOA()
416 soa.dwSerialNo = serial
417 soa.dwRefresh = refresh
419 soa.dwExpire = expire
420 soa.NamePrimaryServer.str = mname
421 soa.NamePrimaryServer.len = len(mname)
422 soa.ZoneAdministratorEmail.str = rname
423 soa.ZoneAdministratorEmail.len = len(rname)
426 class SRVRecord(dnsserver.DNS_RPC_RECORD):
427 def __init__(self, target, port, priority=0, weight=100, serial=1, ttl=900,
428 rank=dnsp.DNS_RANK_ZONE, node_flag=0):
429 super(SRVRecord, self).__init__()
430 self.wType = dnsp.DNS_TYPE_SRV
431 self.dwFlags = rank | node_flag
432 self.dwSerial = serial
433 self.dwTtlSeconds = ttl
434 srv = dnsserver.DNS_RPC_RECORD_SRV()
435 srv.wPriority = priority
438 srv.nameTarget.str = target
439 srv.nameTarget.len = len(target)
442 def dns_record_match(dns_conn, server, zone, name, record_type, data):
443 select_flags = dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
446 buflen, res = dns_conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
456 except RuntimeError, e:
460 if res and res.count > 0:
462 for rec in recs.records:
463 if rec.wType == record_type:
469 if record_type == dnsp.DNS_TYPE_A:
470 if rec_match.data == data:
472 elif record_type == dnsp.DNS_TYPE_AAAA:
473 if rec_match.data == data:
475 elif record_type == dnsp.DNS_TYPE_CNAME:
476 if rec_match.data == data:
478 elif record_type == dnsp.DNS_TYPE_NS:
479 if rec_match.data == data:
488 class cmd_serverinfo(Command):
489 """Query for Server information"""
491 synopsis = '%prog <server> [options]'
493 takes_args = [ 'server' ]
496 Option('--client-version', help='Client Version', default='longhorn',
497 choices=['w2k','dotnet','longhorn'], dest='cli_ver'),
500 def run(self, server, cli_ver, sambaopts=None, credopts=None, versionopts=None):
501 self.lp = sambaopts.get_loadparm()
502 self.creds = credopts.get_credentials(self.lp)
503 dns_conn = dns_connect(server, self.lp, self.creds)
505 client_version = dns_client_version(cli_ver)
507 typeid, res = dns_conn.DnssrvQuery2(client_version,
512 print_serverinfo(self.outf, typeid, res)
515 class cmd_zoneinfo(Command):
516 """Query for zone information"""
518 synopsis = '%prog <server> <zone> [options]'
520 takes_args = [ 'server', 'zone' ]
523 Option('--client-version', help='Client Version', default='longhorn',
524 choices=['w2k','dotnet','longhorn'], dest='cli_ver'),
527 def run(self, server, zone, cli_ver, sambaopts=None, credopts=None, versionopts=None):
528 self.lp = sambaopts.get_loadparm()
529 self.creds = credopts.get_credentials(self.lp)
530 dns_conn = dns_connect(server, self.lp, self.creds)
532 client_version = dns_client_version(cli_ver)
534 typeid, res = dns_conn.DnssrvQuery2(client_version,
539 print_zoneinfo(self.outf, typeid, res)
542 class cmd_zonelist(Command):
543 """Query for zones"""
545 synopsis = '%prog <server> [options]'
547 takes_args = [ 'server' ]
550 Option('--client-version', help='Client Version', default='longhorn',
551 choices=['w2k','dotnet','longhorn'], dest='cli_ver'),
552 Option('--primary', help='List primary zones (default)',
553 action='store_true', dest='primary'),
554 Option('--secondary', help='List secondary zones',
555 action='store_true', dest='secondary'),
556 Option('--cache', help='List cached zones',
557 action='store_true', dest='cache'),
558 Option('--auto', help='List automatically created zones',
559 action='store_true', dest='auto'),
560 Option('--forward', help='List forward zones',
561 action='store_true', dest='forward'),
562 Option('--reverse', help='List reverse zones',
563 action='store_true', dest='reverse'),
564 Option('--ds', help='List directory integrated zones',
565 action='store_true', dest='ds'),
566 Option('--non-ds', help='List non-directory zones',
567 action='store_true', dest='nonds')
570 def run(self, server, cli_ver, primary=False, secondary=False, cache=False,
571 auto=False, forward=False, reverse=False, ds=False, nonds=False,
572 sambaopts=None, credopts=None, versionopts=None):
576 request_filter |= dnsserver.DNS_ZONE_REQUEST_PRIMARY
578 request_filter |= dnsserver.DNS_ZONE_REQUEST_SECONDARY
580 request_filter |= dnsserver.DNS_ZONE_REQUEST_CACHE
582 request_filter |= dnsserver.DNS_ZONE_REQUEST_AUTO
584 request_filter |= dnsserver.DNS_ZONE_REQUEST_FORWARD
586 request_filter |= dnsserver.DNS_ZONE_REQUEST_REVERSE
588 request_filter |= dnsserver.DNS_ZONE_REQUEST_DS
590 request_filter |= dnsserver.DNS_ZONE_REQUEST_NON_DS
592 if request_filter == 0:
593 request_filter = dnsserver.DNS_ZONE_REQUEST_PRIMARY
595 self.lp = sambaopts.get_loadparm()
596 self.creds = credopts.get_credentials(self.lp)
597 dns_conn = dns_connect(server, self.lp, self.creds)
599 client_version = dns_client_version(cli_ver)
601 typeid, res = dns_conn.DnssrvComplexOperation2(client_version,
606 dnsserver.DNSSRV_TYPEID_DWORD,
609 if client_version == dnsserver.DNS_CLIENT_VERSION_W2K:
610 typeid = dnsserver.DNSSRV_TYPEID_ZONE_W2K
612 typeid = dnsserver.DNSSRV_TYPEID_ZONE
613 print_enumzones(self.outf, typeid, res)
616 class cmd_query(Command):
619 synopsis = '%prog <server> <zone> <name> <type> [options]'
621 takes_args = [ 'server', 'zone', 'name', 'rtype' ]
624 Option('--authority', help='Search authoritative records (default)',
625 action='store_true', dest='authority'),
626 Option('--cache', help='Search cached records',
627 action='store_true', dest='cache'),
628 Option('--glue', help='Search glue records',
629 action='store_true', dest='glue'),
630 Option('--root', help='Search root hints',
631 action='store_true', dest='root'),
632 Option('--additional', help='List additional records',
633 action='store_true', dest='additional'),
634 Option('--no-children', help='Do not list children',
635 action='store_true', dest='no_children'),
636 Option('--only-children', help='List only children',
637 action='store_true', dest='only_children')
640 def run(self, server, zone, name, rtype, authority=False, cache=False, glue=False,
641 root=False, additional=False, no_children=False, only_children=False,
642 sambaopts=None, credopts=None, versionopts=None):
643 record_type = dns_type_flag(rtype)
647 select_flags |= dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
649 select_flags |= dnsserver.DNS_RPC_VIEW_CACHE_DATA
651 select_flags |= dnsserver.DNS_RPC_VIEW_GLUE_DATA
653 select_flags |= dnsserver.DNS_RPC_VIEW_ROOT_HINT_DATA
655 select_flags |= dnsserver.DNS_RPC_VIEW_ADDITIONAL_DATA
657 select_flags |= dnsserver.DNS_RPC_VIEW_NO_CHILDREN
659 select_flags |= dnsserver.DNS_RPC_VIEW_ONLY_CHILDREN
661 if select_flags == 0:
662 select_flags = dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
664 self.lp = sambaopts.get_loadparm()
665 self.creds = credopts.get_credentials(self.lp)
666 dns_conn = dns_connect(server, self.lp, self.creds)
668 buflen, res = dns_conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
678 print_dnsrecords(self.outf, res)
681 class cmd_roothints(Command):
682 """Query root hints"""
684 synopsis = '%prog <server> [<name>] [options]'
686 takes_args = [ 'server', 'name?' ]
688 def run(self, server, name='.', sambaopts=None, credopts=None, versionopts=None):
689 record_type = dnsp.DNS_TYPE_NS
690 select_flags = (dnsserver.DNS_RPC_VIEW_ROOT_HINT_DATA |
691 dnsserver.DNS_RPC_VIEW_ADDITIONAL_DATA)
693 self.lp = sambaopts.get_loadparm()
694 self.creds = credopts.get_credentials(self.lp)
695 dns_conn = dns_connect(server, self.lp, self.creds)
697 buflen, res = dns_conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
707 print_dnsrecords(self.outf, res)
710 class cmd_add_record(Command):
711 """Add a DNS record"""
713 synopsis = '%prog <server> <zone> <name> <A|AAAA|CNAME|NS> <data>'
715 takes_args = [ 'server', 'zone', 'name', 'rtype', 'data' ]
717 def run(self, server, zone, name, rtype, data, sambaopts=None, credopts=None, versionopts=None):
719 record_type = dns_type_flag(rtype)
721 if record_type == dnsp.DNS_TYPE_A:
723 elif record_type == dnsp.DNS_TYPE_AAAA:
724 rec = AAAARecord(data)
725 elif record_type == dnsp.DNS_TYPE_CNAME:
726 rec = CNameRecord(data)
727 elif record_type == dnsp.DNS_TYPE_NS:
730 raise CommandError('Adding record of type %s is not supported' % rtype)
732 self.lp = sambaopts.get_loadparm()
733 self.creds = credopts.get_credentials(self.lp)
734 dns_conn = dns_connect(server, self.lp, self.creds)
736 rec_match = dns_record_match(dns_conn, server, zone, name, record_type, data)
737 if rec_match is not None:
738 raise CommandError('Record already exists')
740 add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
741 add_rec_buf.rec = rec
743 dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
750 self.outf.write('Record added succefully\n')
753 class cmd_update_record(Command):
754 """Update a DNS record"""
756 synopsis = '%prog <server> <zone> <name> <A|AAAA|CNAME|NS> <olddata> <newdata>'
758 takes_args = [ 'server', 'zone', 'name', 'rtype', 'olddata', 'newdata' ]
760 def run(self, server, zone, name, rtype, olddata, newdata,
761 sambaopts=None, credopts=None, versionopts=None):
763 record_type = dns_type_flag(rtype)
764 if record_type == dnsp.DNS_TYPE_A:
765 rec = ARecord(newdata)
766 elif record_type == dnsp.DNS_TYPE_AAAA:
767 rec = AAAARecord(newdata)
768 elif record_type == dnsp.DNS_TYPE_CNAME:
769 rec = CNameRecord(newdata)
770 elif record_type == dnsp.DNS_TYPE_NS:
771 rec = NSRecord(newdata)
773 raise CommandError('Updating record of type %s is not supported' % rtype)
775 self.lp = sambaopts.get_loadparm()
776 self.creds = credopts.get_credentials(self.lp)
777 dns_conn = dns_connect(server, self.lp, self.creds)
779 rec_match = dns_record_match(dns_conn, server, zone, name, record_type, olddata)
781 raise CommandError('Record does not exist')
783 # Copy properties from existing record to new record
784 rec.dwFlags = rec_match.dwFlags
785 rec.dwSerial = rec_match.dwSerial
786 rec.dwTtlSeconds = rec_match.dwTtlSeconds
787 rec.dwTimeStamp = rec_match.dwTimeStamp
789 add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
790 add_rec_buf.rec = rec
792 del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
793 del_rec_buf.rec = rec_match
795 dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
802 self.outf.write('Record updated succefully\n')
805 class cmd_delete_record(Command):
806 """Delete a DNS record"""
808 synopsis = '%prog <server> <zone> <name> <A|AAAA|CNAME|NS> <data>'
810 takes_args = [ 'server', 'zone', 'name', 'rtype', 'data' ]
812 def run(self, server, zone, name, rtype, data, sambaopts=None, credopts=None, versionopts=None):
814 record_type = dns_type_flag(rtype)
816 if record_type == dnsp.DNS_TYPE_A:
818 elif record_type == dnsp.DNS_TYPE_AAAA:
819 rec = AAAARecord(data)
820 elif record_type == dnsp.DNS_TYPE_CNAME:
821 rec = CNameRecord(data)
822 elif record_type == dnsp.DNS_TYPE_NS:
825 raise CommandError('Deleting record of type %s is not supported' % rtype)
827 self.lp = sambaopts.get_loadparm()
828 self.creds = credopts.get_credentials(self.lp)
829 dns_conn = dns_connect(server, self.lp, self.creds)
831 rec_match = dns_record_match(dns_conn, server, zone, name, record_type, data)
833 raise CommandError('Record does not exist')
835 del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
836 del_rec_buf.rec = rec_match
838 dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
845 self.outf.write('Record deleted succefully\n')
848 class cmd_dns(SuperCommand):
849 """Domain Name Service (DNS) management"""
852 subcommands['serverinfo'] = cmd_serverinfo()
853 subcommands['zoneinfo'] = cmd_zoneinfo()
854 subcommands['zonelist'] = cmd_zonelist()
855 subcommands['query'] = cmd_query()
856 subcommands['roothints'] = cmd_roothints()
857 subcommands['add'] = cmd_add_record()
858 subcommands['update'] = cmd_update_record()
859 subcommands['delete'] = cmd_delete_record()