Some formatting fixes, remove unused imports.
[Samba/gebeck_regimport.git] / source4 / scripting / python / samba / netcmd / dns.py
blob3c1bb98160141da5864bba3aaf20f72ef865de32
1 #!/usr/bin/env python
3 # DNS management tool
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/>.
21 import samba.getopt as options
22 from struct import pack
23 from socket import inet_ntoa
25 from samba.netcmd import (
26 Command,
27 CommandError,
28 Option,
29 SuperCommand,
31 from samba.dcerpc import dnsp, dnsserver
34 def dns_connect(server, lp, creds):
35 binding_str = "ncacn_ip_tcp:%s[sign]" % server
36 dns_conn = dnsserver.dnsserver(binding_str, lp, creds)
37 return dns_conn
39 def bool_string(flag):
40 if flag == 0:
41 ret = 'FALSE'
42 elif flag == 1:
43 ret = 'TRUE'
44 else:
45 ret = 'UNKNOWN (0x%x)' % flag
46 return ret
48 def enum_string(module, enum_defs, value):
49 ret = None
50 for e in enum_defs:
51 if value == getattr(module, e):
52 ret = e
53 break
54 if not ret:
55 ret = 'UNKNOWN (0x%x)' % value
56 return ret
58 def bitmap_string(module, bitmap_defs, value):
59 ret = ''
60 for b in bitmap_defs:
61 if value & getattr(module, b):
62 ret += '%s ' % b
63 if not ret:
64 ret = 'NONE'
65 return ret
67 def boot_method_string(boot_method):
68 enum_defs = [ 'DNS_BOOT_METHOD_UNINITIALIZED', 'DNS_BOOT_METHOD_FILE',
69 'DNS_BOOT_METHOD_REGISTRY', 'DNS_BOOT_METHOD_DIRECTORY' ]
70 return enum_string(dnsserver, enum_defs, boot_method)
72 def name_check_flag_string(check_flag):
73 enum_defs = [ 'DNS_ALLOW_RFC_NAMES_ONLY', 'DNS_ALLOW_NONRFC_NAMES',
74 'DNS_ALLOW_MULTIBYTE_NAMES', 'DNS_ALLOW_ALL_NAMES' ]
75 return enum_string(dnsserver, enum_defs, check_flag)
77 def zone_type_string(zone_type):
78 enum_defs = [ 'DNS_ZONE_TYPE_CACHE', 'DNS_ZONE_TYPE_PRIMARY',
79 'DNS_ZONE_TYPE_SECONDARY', 'DNS_ZONE_TYPE_STUB',
80 'DNS_ZONE_TYPE_FORWARDER', 'DNS_ZONE_TYPE_SECONDARY_CACHE' ]
81 return enum_string(dnsp, enum_defs, zone_type)
83 def zone_update_string(zone_update):
84 enum_defs = [ 'DNS_ZONE_UPDATE_OFF', 'DNS_ZONE_UPDATE_SECURE',
85 'DNS_ZONE_UPDATE_SECURE' ]
86 return enum_string(dnsp, enum_defs, zone_update)
88 def zone_secondary_security_string(security):
89 enum_defs = [ 'DNS_ZONE_SECSECURE_NO_SECURITY', 'DNS_ZONE_SECSECURE_NS_ONLY',
90 'DNS_ZONE_SECSECURE_LIST_ONLY', 'DNS_ZONE_SECSECURE_NO_XFER' ]
91 return enum_string(dnsserver, enum_defs, security)
93 def zone_notify_level_string(notify_level):
94 enum_defs = [ 'DNS_ZONE_NOTIFY_OFF', 'DNS_ZONE_NOTIFY_ALL_SECONDARIES',
95 'DNS_ZONE_NOTIFY_LIST_ONLY' ]
96 return enum_string(dnsserver, enum_defs, notify_level)
98 def dp_flags_string(dp_flags):
99 bitmap_defs = [ 'DNS_DP_AUTOCREATED', 'DNS_DP_LEGACY', 'DNS_DP_DOMAIN_DEFAULT',
100 'DNS_DP_FOREST_DEFAULT', 'DNS_DP_ENLISTED', 'DNS_DP_DELETED' ]
101 return bitmap_string(dnsserver, bitmap_defs, dp_flags)
103 def zone_flags_string(flags):
104 bitmap_defs = [ 'DNS_RPC_ZONE_PAUSED', 'DNS_RPC_ZONE_SHUTDOWN',
105 'DNS_RPC_ZONE_REVERSE', 'DNS_RPC_ZONE_AUTOCREATED',
106 'DNS_RPC_ZONE_DSINTEGRATED', 'DNS_RPC_ZONE_AGING',
107 'DNS_RPC_ZONE_UPDATE_UNSECURE', 'DNS_RPC_ZONE_UPDATE_SECURE',
108 'DNS_RPC_ZONE_READONLY']
109 return bitmap_string(dnsserver, bitmap_defs, flags)
111 def ip4_array_string(array):
112 ret = []
113 if not array:
114 return ret
115 for i in xrange(array.AddrCount):
116 addr = '%s' % inet_ntoa(pack('i', array.AddrArray[i]))
117 ret.append(addr)
118 return ret
120 def dns_addr_array_string(array):
121 ret = []
122 if not array:
123 return ret
124 for i in xrange(array.AddrCount):
125 if array.AddrArray[i].MaxSa[0] == 0x02:
126 addr = '%d.%d.%d.%d (%d)' % \
127 tuple(array.AddrArray[i].MaxSa[4:8] + [array.AddrArray[i].MaxSa[3]])
128 elif array.AddrArray[i].MaxSa[0] == 0x17:
129 addr = '%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x (%d)' % \
130 tuple(array.AddrArray[i].MaxSa[4:20] + [array.AddrArray[i].MaxSa[3]])
131 else:
132 addr = 'UNKNOWN'
133 ret.append(addr)
134 return ret
136 def dns_type_flag(rec_type):
137 rtype = rec_type.upper()
138 if rtype == 'A':
139 record_type = dnsp.DNS_TYPE_A
140 elif rtype == 'AAAA':
141 record_type = dnsp.DNS_TYPE_AAAA
142 elif rtype == 'NS':
143 record_type = dnsp.DNS_TYPE_NS
144 elif rtype == 'CNAME':
145 record_type = dnsp.DNS_TYPE_CNAME
146 elif rtype == 'SOA':
147 record_type = dnsp.DNS_TYPE_SOA
148 elif rtype == 'MX':
149 record_type = dnsp.DNS_TYPE_MX
150 elif rtype == 'SRV':
151 record_type = dnsp.DNS_TYPE_SRV
152 elif rtype == 'ALL':
153 record_type = dnsp.DNS_TYPE_ALL
154 else:
155 raise CommandError('Unknown type of DNS record %s' % rec_type)
156 return record_type
158 def dns_client_version(cli_version):
159 version = cli_version.upper()
160 if version == 'W2K':
161 client_version = dnsserver.DNS_CLIENT_VERSION_W2K
162 elif version == 'DOTNET':
163 client_version = dnsserver.DNS_CLIENT_VERSION_DOTNET
164 elif version == 'LONGHORN':
165 client_version = dnsserver.DNS_CLIENT_VERSION_LONGHORN
166 else:
167 raise CommandError('Unknown client version %s' % cli_version)
168 return client_version
170 def print_serverinfo(outf, typeid, serverinfo):
171 outf.write(' dwVersion : 0x%x\n' % serverinfo.dwVersion)
172 outf.write(' fBootMethod : %s\n' % boot_method_string(serverinfo.fBootMethod))
173 outf.write(' fAdminConfigured : %s\n' % bool_string(serverinfo.fAdminConfigured))
174 outf.write(' fAllowUpdate : %s\n' % bool_string(serverinfo.fAllowUpdate))
175 outf.write(' fDsAvailable : %s\n' % bool_string(serverinfo.fDsAvailable))
176 outf.write(' pszServerName : %s\n' % serverinfo.pszServerName)
177 outf.write(' pszDsContainer : %s\n' % serverinfo.pszDsContainer)
179 if typeid != dnsserver.DNSSRV_TYPEID_SERVER_INFO:
180 outf.write(' aipServerAddrs : %s\n' %
181 ip4_array_string(serverinfo.aipServerAddrs))
182 outf.write(' aipListenAddrs : %s\n' %
183 ip4_array_string(serverinfo.aipListenAddrs))
184 outf.write(' aipForwarders : %s\n' %
185 ip4_array_string(serverinfo.aipForwarders))
186 else:
187 outf.write(' aipServerAddrs : %s\n' %
188 dns_addr_array_string(serverinfo.aipServerAddrs))
189 outf.write(' aipListenAddrs : %s\n' %
190 dns_addr_array_string(serverinfo.aipListenAddrs))
191 outf.write(' aipForwarders : %s\n' %
192 dns_addr_array_string(serverinfo.aipForwarders))
194 outf.write(' dwLogLevel : %d\n' % serverinfo.dwLogLevel)
195 outf.write(' dwDebugLevel : %d\n' % serverinfo.dwDebugLevel)
196 outf.write(' dwForwardTimeout : %d\n' % serverinfo.dwForwardTimeout)
197 outf.write(' dwRpcPrototol : 0x%x\n' % serverinfo.dwRpcProtocol)
198 outf.write(' dwNameCheckFlag : %s\n' % name_check_flag_string(serverinfo.dwNameCheckFlag))
199 outf.write(' cAddressAnswerLimit : %d\n' % serverinfo.cAddressAnswerLimit)
200 outf.write(' dwRecursionRetry : %d\n' % serverinfo.dwRecursionRetry)
201 outf.write(' dwRecursionTimeout : %d\n' % serverinfo.dwRecursionTimeout)
202 outf.write(' dwMaxCacheTtl : %d\n' % serverinfo.dwMaxCacheTtl)
203 outf.write(' dwDsPollingInterval : %d\n' % serverinfo.dwDsPollingInterval)
204 outf.write(' dwScavengingInterval : %d\n' % serverinfo.dwScavengingInterval)
205 outf.write(' dwDefaultRefreshInterval : %d\n' % serverinfo.dwDefaultRefreshInterval)
206 outf.write(' dwDefaultNoRefreshInterval : %d\n' % serverinfo.dwDefaultNoRefreshInterval)
207 outf.write(' fAutoReverseZones : %s\n' % bool_string(serverinfo.fAutoReverseZones))
208 outf.write(' fAutoCacheUpdate : %s\n' % bool_string(serverinfo.fAutoCacheUpdate))
209 outf.write(' fRecurseAfterForwarding : %s\n' % bool_string(serverinfo.fRecurseAfterForwarding))
210 outf.write(' fForwardDelegations : %s\n' % bool_string(serverinfo.fForwardDelegations))
211 outf.write(' fNoRecursion : %s\n' % bool_string(serverinfo.fNoRecursion))
212 outf.write(' fSecureResponses : %s\n' % bool_string(serverinfo.fSecureResponses))
213 outf.write(' fRoundRobin : %s\n' % bool_string(serverinfo.fRoundRobin))
214 outf.write(' fLocalNetPriority : %s\n' % bool_string(serverinfo.fLocalNetPriority))
215 outf.write(' fBindSecondaries : %s\n' % bool_string(serverinfo.fBindSecondaries))
216 outf.write(' fWriteAuthorityNs : %s\n' % bool_string(serverinfo.fWriteAuthorityNs))
217 outf.write(' fStrictFileParsing : %s\n' % bool_string(serverinfo.fStrictFileParsing))
218 outf.write(' fLooseWildcarding : %s\n' % bool_string(serverinfo.fLooseWildcarding))
219 outf.write(' fDefaultAgingState : %s\n' % bool_string(serverinfo.fDefaultAgingState))
221 if typeid != dnsserver.DNSSRV_TYPEID_SERVER_INFO_W2K:
222 outf.write(' dwRpcStructureVersion : 0x%x\n' % serverinfo.dwRpcStructureVersion)
223 outf.write(' aipLogFilter : %s\n' % dns_addr_array_string(serverinfo.aipLogFilter))
224 outf.write(' pwszLogFilePath : %s\n' % serverinfo.pwszLogFilePath)
225 outf.write(' pszDomainName : %s\n' % serverinfo.pszDomainName)
226 outf.write(' pszForestName : %s\n' % serverinfo.pszForestName)
227 outf.write(' pszDomainDirectoryPartition : %s\n' % serverinfo.pszDomainDirectoryPartition)
228 outf.write(' pszForestDirectoryPartition : %s\n' % serverinfo.pszForestDirectoryPartition)
230 outf.write(' dwLocalNetPriorityNetMask : 0x%x\n' % serverinfo.dwLocalNetPriorityNetMask)
231 outf.write(' dwLastScavengeTime : %d\n' % serverinfo.dwLastScavengeTime)
232 outf.write(' dwEventLogLevel : %d\n' % serverinfo.dwEventLogLevel)
233 outf.write(' dwLogFileMaxSize : %d\n' % serverinfo.dwLogFileMaxSize)
234 outf.write(' dwDsForestVersion : %d\n' % serverinfo.dwDsForestVersion)
235 outf.write(' dwDsDomainVersion : %d\n' % serverinfo.dwDsDomainVersion)
236 outf.write(' dwDsDsaVersion : %d\n' % serverinfo.dwDsDsaVersion)
238 if typeid == dnsserver.DNSSRV_TYPEID_SERVER_INFO:
239 outf.write(' fReadOnlyDC : %s\n' % bool_string(serverinfo.fReadOnlyDC))
242 def print_zoneinfo(outf, typeid, zoneinfo):
243 outf.write(' pszZoneName : %s\n' % zoneinfo.pszZoneName)
244 outf.write(' dwZoneType : %s\n' % zone_type_string(zoneinfo.dwZoneType))
245 outf.write(' fReverse : %s\n' % bool_string(zoneinfo.fReverse))
246 outf.write(' fAllowUpdate : %s\n' % zone_update_string(zoneinfo.fAllowUpdate))
247 outf.write(' fPaused : %s\n' % bool_string(zoneinfo.fPaused))
248 outf.write(' fShutdown : %s\n' % bool_string(zoneinfo.fShutdown))
249 outf.write(' fAutoCreated : %s\n' % bool_string(zoneinfo.fAutoCreated))
250 outf.write(' fUseDatabase : %s\n' % bool_string(zoneinfo.fUseDatabase))
251 outf.write(' pszDataFile : %s\n' % zoneinfo.pszDataFile)
252 if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
253 outf.write(' aipMasters : %s\n' %
254 ip4_array_string(zoneinfo.aipMasters))
255 else:
256 outf.write(' aipMasters : %s\n' %
257 dns_addr_array_string(zoneinfo.aipMasters))
258 outf.write(' fSecureSecondaries : %s\n' % zone_secondary_security_string(zoneinfo.fSecureSecondaries))
259 outf.write(' fNotifyLevel : %s\n' % zone_notify_level_string(zoneinfo.fNotifyLevel))
260 if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
261 outf.write(' aipSecondaries : %s\n' %
262 ip4_array_string(zoneinfo.aipSecondaries))
263 outf.write(' aipNotify : %s\n' %
264 ip4_array_string(zoneinfo.aipNotify))
265 else:
266 outf.write(' aipSecondaries : %s\n' %
267 dns_addr_array_string(zoneinfo.aipSecondaries))
268 outf.write(' aipNotify : %s\n' %
269 dns_addr_array_string(zoneinfo.aipNotify))
270 outf.write(' fUseWins : %s\n' % bool_string(zoneinfo.fUseWins))
271 outf.write(' fUseNbstat : %s\n' % bool_string(zoneinfo.fUseNbstat))
272 outf.write(' fAging : %s\n' % bool_string(zoneinfo.fAging))
273 outf.write(' dwNoRefreshInterval : %d\n' % zoneinfo.dwNoRefreshInterval)
274 outf.write(' dwRefreshInterval : %d\n' % zoneinfo.dwRefreshInterval)
275 outf.write(' dwAvailForScavengeTime : %d\n' % zoneinfo.dwAvailForScavengeTime)
276 if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
277 outf.write(' aipScavengeServers : %s\n' %
278 ip4_array_string(zoneinfo.aipScavengeServers))
279 else:
280 outf.write(' aipScavengeServers : %s\n' %
281 dns_addr_array_string(zoneinfo.aipScavengeServers))
283 if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO_W2K:
284 outf.write(' dwRpcStructureVersion : 0x%x\n' % zoneinfo.dwRpcStructureVersion)
285 outf.write(' dwForwarderTimeout : %d\n' % zoneinfo.dwForwarderTimeout)
286 outf.write(' fForwarderSlave : %d\n' % zoneinfo.fForwarderSlave)
287 if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
288 outf.write(' aipLocalMasters : %s\n' %
289 ip4_array_string(zoneinfo.aipLocalMasters))
290 else:
291 outf.write(' aipLocalMasters : %s\n' %
292 dns_addr_array_string(zoneinfo.aipLocalMasters))
293 outf.write(' dwDpFlags : %s\n' % dp_flags_string(zoneinfo.dwDpFlags))
294 outf.write(' pszDpFqdn : %s\n' % zoneinfo.pszDpFqdn)
295 outf.write(' pwszZoneDn : %s\n' % zoneinfo.pwszZoneDn)
296 outf.write(' dwLastSuccessfulSoaCheck : %d\n' % zoneinfo.dwLastSuccessfulSoaCheck)
297 outf.write(' dwLastSuccessfulXfr : %d\n' % zoneinfo.dwLastSuccessfulXfr)
299 if typeid == dnsserver.DNSSRV_TYPEID_ZONE_INFO:
300 outf.write(' fQueuedForBackgroundLoad : %s\n' % bool_string(zoneinfo.fQueuedForBackgroundLoad))
301 outf.write(' fBackgroundLoadInProgress : %s\n' % bool_string(zoneinfo.fBackgroundLoadInProgress))
302 outf.write(' fReadOnlyZone : %s\n' % bool_string(zoneinfo.fReadOnlyZone))
303 outf.write(' dwLastXfrAttempt : %d\n' % zoneinfo.dwLastXfrAttempt)
304 outf.write(' dwLastXfrResult : %d\n' % zoneinfo.dwLastXfrResult)
307 def print_zone(outf, typeid, zone):
308 outf.write(' pszZoneName : %s\n' % zone.pszZoneName)
309 outf.write(' Flags : %s\n' % zone_flags_string(zone.Flags))
310 outf.write(' ZoneType : %s\n' % zone_type_string(zone.ZoneType))
311 outf.write(' Version : %s\n' % zone.Version)
313 if typeid != dnsserver.DNSSRV_TYPEID_ZONE_W2K:
314 outf.write(' dwDpFlags : %s\n' % dp_flags_string(zone.dwDpFlags))
315 outf.write(' pszDpFqdn : %s\n' % zone.pszDpFqdn)
318 def print_enumzones(outf, typeid, zones):
319 outf.write(' %d zone(s) found\n' % zones.dwZoneCount)
320 for zone in zones.ZoneArray:
321 outf.write('\n')
322 print_zone(outf, typeid, zone)
325 def print_dns_record(outf, rec):
326 mesg = 'Unknown: '
327 if rec.wType == dnsp.DNS_TYPE_A:
328 mesg = 'A: %s' % (rec.data)
329 elif rec.wType == dnsp.DNS_TYPE_NS:
330 mesg = 'NS: %s' % (rec.data.str)
331 elif rec.wType == dnsp.DNS_TYPE_CNAME:
332 mesg = 'CNAME: %s' % (rec.data.str)
333 elif rec.wType == dnsp.DNS_TYPE_SOA:
334 mesg = 'SOA: serial=%d, refresh=%d, retry=%d, expire=%d, ns=%s, email=%s' % (
335 rec.data.dwSerialNo,
336 rec.data.dwRefresh,
337 rec.data.dwRetry,
338 rec.data.dwExpire,
339 rec.data.NamePrimaryServer.str,
340 rec.data.ZoneAdministratorEmail.str)
341 elif rec.wType == dnsp.DNS_TYPE_MX:
342 mesg = 'MX: %s' % (rec.data.str)
343 elif rec.wType == dnsp.DNS_TYPE_SRV:
344 mesg = 'SRV: %s (%d)' % (rec.data.nameTarget.str, rec.data.wPort)
345 outf.write(' %s (flags=%x, serial=%d, ttl=%d)\n' % (
346 mesg, rec.dwFlags, rec.dwSerial, rec.dwTtlSeconds))
349 def print_dnsrecords(outf, records):
350 for rec in records.rec:
351 outf.write(' Name=%s, Records=%d, Children=%d\n' % (
352 rec.dnsNodeName.str,
353 rec.wRecordCount,
354 rec.dwChildCount))
355 for dns_rec in rec.records:
356 print_dns_record(outf, dns_rec)
359 class ARecord(dnsserver.DNS_RPC_RECORD):
360 def __init__(self, ip_addr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
361 node_flag=0):
362 super(ARecord, self).__init__()
363 self.wType = dnsp.DNS_TYPE_A
364 self.dwFlags = rank | node_flag
365 self.dwSerial = serial
366 self.dwTtlSeconds = ttl
367 self.data = ip_addr
369 class AAAARecord(dnsserver.DNS_RPC_RECORD):
370 def __init__(self, ip6_addr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
371 node_flag=0):
372 super(AAAARecord, self).__init__()
373 self.wType = dnsp.DNS_TYPE_AAAA
374 self.dwFlags = rank | node_flag
375 self.dwSerial = serial
376 self.dwTtlSeconds = ttl
377 self.data = ip6_addr
379 class CNameRecord(dnsserver.DNS_RPC_RECORD):
380 def __init__(self, cname, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
381 node_flag=0):
382 super(CNameRecord, self).__init__()
383 self.wType = dnsp.DNS_TYPE_CNAME
384 self.dwFlags = rank | node_flag
385 self.dwSerial = serial
386 self.dwTtlSeconds = ttl
387 cname_name = dnsserver.DNS_RPC_NAME()
388 cname_name.str = cname
389 cname_name.len = len(cname)
390 self.data = cname_name
392 class NSRecord(dnsserver.DNS_RPC_RECORD):
393 def __init__(self, dns_server, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
394 node_flag=0):
395 super(NSRecord, self).__init__()
396 self.wType = dnsp.DNS_TYPE_NS
397 self.dwFlags = rank | node_flag
398 self.dwSerial = serial
399 self.dwTtlSeconds = ttl
400 ns = dnsserver.DNS_RPC_NAME()
401 ns.str = dns_server
402 ns.len = len(dns_server)
403 self.data = ns
405 class SOARecord(dnsserver.DNS_RPC_RECORD):
406 def __init__(self, mname, rname, serial=1, refresh=900, retry=600,
407 expire=86400, minimum=3600, ttl=3600, rank=dnsp.DNS_RANK_ZONE,
408 node_flag=dnsp.DNS_RPC_FLAG_AUTH_ZONE_ROOT):
409 super(SOARecord, self).__init__()
410 self.wType = dnsp.DNS_TYPE_SOA
411 self.dwFlags = rank | node_flag
412 self.dwSerial = serial
413 self.dwTtlSeconds = ttl
414 soa = dnsserver.DNS_RPC_RECORD_SOA()
415 soa.dwSerialNo = serial
416 soa.dwRefresh = refresh
417 soa.dwRetry = retry
418 soa.dwExpire = expire
419 soa.NamePrimaryServer.str = mname
420 soa.NamePrimaryServer.len = len(mname)
421 soa.ZoneAdministratorEmail.str = rname
422 soa.ZoneAdministratorEmail.len = len(rname)
423 self.data = soa
425 class SRVRecord(dnsserver.DNS_RPC_RECORD):
426 def __init__(self, target, port, priority=0, weight=100, serial=1, ttl=900,
427 rank=dnsp.DNS_RANK_ZONE, node_flag=0):
428 super(SRVRecord, self).__init__()
429 self.wType = dnsp.DNS_TYPE_SRV
430 self.dwFlags = rank | node_flag
431 self.dwSerial = serial
432 self.dwTtlSeconds = ttl
433 srv = dnsserver.DNS_RPC_RECORD_SRV()
434 srv.wPriority = priority
435 srv.wWeight = weight
436 srv.wPort = port
437 srv.nameTarget.str = target
438 srv.nameTarget.len = len(target)
439 self.data = srv
441 def dns_record_match(dns_conn, server, zone, name, record_type, data):
442 select_flags = dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
444 try:
445 buflen, res = dns_conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
447 server,
448 zone,
449 name,
450 None,
451 record_type,
452 select_flags,
453 None,
454 None)
455 except RuntimeError, e:
456 return None
458 rec_match = None
459 if res and res.count > 0:
460 recs = res.rec[0]
461 for rec in recs.records:
462 if rec.wType == record_type:
463 rec_match = rec
464 break
466 if rec_match:
467 found = False
468 if record_type == dnsp.DNS_TYPE_A:
469 if rec_match.data == data:
470 found = True
471 elif record_type == dnsp.DNS_TYPE_AAAA:
472 if rec_match.data == data:
473 found = True
474 elif record_type == dnsp.DNS_TYPE_CNAME:
475 if rec_match.data == data:
476 found = True
477 elif record_type == dnsp.DNS_TYPE_NS:
478 if rec_match.data == data:
479 found = True
481 if found:
482 return rec_match
484 return None
487 class cmd_serverinfo(Command):
488 """Query for Server information"""
490 synopsis = '%prog <server> [options]'
492 takes_args = [ 'server' ]
494 takes_options = [
495 Option('--client-version', help='Client Version',
496 default='longhorn', metavar='w2k|dotnet|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,
509 server,
510 None,
511 'ServerInfo')
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' ]
522 takes_options = [
523 Option('--client-version', help='Client Version',
524 default='longhorn', metavar='w2k|dotnet|longhorn',
525 choices=['w2k','dotnet','longhorn'], dest='cli_ver'),
528 def run(self, server, zone, cli_ver, sambaopts=None, credopts=None, versionopts=None):
529 self.lp = sambaopts.get_loadparm()
530 self.creds = credopts.get_credentials(self.lp)
531 dns_conn = dns_connect(server, self.lp, self.creds)
533 client_version = dns_client_version(cli_ver)
535 typeid, res = dns_conn.DnssrvQuery2(client_version,
537 server,
538 zone,
539 'ZoneInfo')
540 print_zoneinfo(self.outf, typeid, res)
543 class cmd_zonelist(Command):
544 """Query for zones"""
546 synopsis = '%prog <server> [options]'
548 takes_args = [ 'server' ]
550 takes_options = [
551 Option('--client-version', help='Client Version',
552 default='longhorn', metavar='w2k|dotnet|longhorn',
553 choices=['w2k','dotnet','longhorn'], dest='cli_ver'),
554 Option('--primary', help='List primary zones (default)',
555 action='store_true', dest='primary'),
556 Option('--secondary', help='List secondary zones',
557 action='store_true', dest='secondary'),
558 Option('--cache', help='List cached zones',
559 action='store_true', dest='cache'),
560 Option('--auto', help='List automatically created zones',
561 action='store_true', dest='auto'),
562 Option('--forward', help='List forward zones',
563 action='store_true', dest='forward'),
564 Option('--reverse', help='List reverse zones',
565 action='store_true', dest='reverse'),
566 Option('--ds', help='List directory integrated zones',
567 action='store_true', dest='ds'),
568 Option('--non-ds', help='List non-directory zones',
569 action='store_true', dest='nonds')
572 def run(self, server, cli_ver, primary=False, secondary=False, cache=False,
573 auto=False, forward=False, reverse=False, ds=False, nonds=False,
574 sambaopts=None, credopts=None, versionopts=None):
575 request_filter = 0
577 if primary:
578 request_filter |= dnsserver.DNS_ZONE_REQUEST_PRIMARY
579 if secondary:
580 request_filter |= dnsserver.DNS_ZONE_REQUEST_SECONDARY
581 if cache:
582 request_filter |= dnsserver.DNS_ZONE_REQUEST_CACHE
583 if auto:
584 request_filter |= dnsserver.DNS_ZONE_REQUEST_AUTO
585 if forward:
586 request_filter |= dnsserver.DNS_ZONE_REQUEST_FORWARD
587 if reverse:
588 request_filter |= dnsserver.DNS_ZONE_REQUEST_REVERSE
589 if ds:
590 request_filter |= dnsserver.DNS_ZONE_REQUEST_DS
591 if nonds:
592 request_filter |= dnsserver.DNS_ZONE_REQUEST_NON_DS
594 if request_filter == 0:
595 request_filter = dnsserver.DNS_ZONE_REQUEST_PRIMARY
597 self.lp = sambaopts.get_loadparm()
598 self.creds = credopts.get_credentials(self.lp)
599 dns_conn = dns_connect(server, self.lp, self.creds)
601 client_version = dns_client_version(cli_ver)
603 typeid, res = dns_conn.DnssrvComplexOperation2(client_version,
605 server,
606 None,
607 'EnumZones',
608 dnsserver.DNSSRV_TYPEID_DWORD,
609 request_filter)
611 if client_version == dnsserver.DNS_CLIENT_VERSION_W2K:
612 typeid = dnsserver.DNSSRV_TYPEID_ZONE_W2K
613 else:
614 typeid = dnsserver.DNSSRV_TYPEID_ZONE
615 print_enumzones(self.outf, typeid, res)
618 class cmd_query(Command):
619 """Query a name."""
621 synopsis = '%prog <server> <zone> <name> <A|AAAA|CNAME|MX|NS|SOA|SRV|ALL> [options]'
623 takes_args = [ 'server', 'zone', 'name', 'rtype' ]
625 takes_options = [
626 Option('--authority', help='Search authoritative records (default)',
627 action='store_true', dest='authority'),
628 Option('--cache', help='Search cached records',
629 action='store_true', dest='cache'),
630 Option('--glue', help='Search glue records',
631 action='store_true', dest='glue'),
632 Option('--root', help='Search root hints',
633 action='store_true', dest='root'),
634 Option('--additional', help='List additional records',
635 action='store_true', dest='additional'),
636 Option('--no-children', help='Do not list children',
637 action='store_true', dest='no_children'),
638 Option('--only-children', help='List only children',
639 action='store_true', dest='only_children')
642 def run(self, server, zone, name, rtype, authority=False, cache=False, glue=False,
643 root=False, additional=False, no_children=False, only_children=False,
644 sambaopts=None, credopts=None, versionopts=None):
645 record_type = dns_type_flag(rtype)
647 select_flags = 0
648 if authority:
649 select_flags |= dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
650 if cache:
651 select_flags |= dnsserver.DNS_RPC_VIEW_CACHE_DATA
652 if glue:
653 select_flags |= dnsserver.DNS_RPC_VIEW_GLUE_DATA
654 if root:
655 select_flags |= dnsserver.DNS_RPC_VIEW_ROOT_HINT_DATA
656 if additional:
657 select_flags |= dnsserver.DNS_RPC_VIEW_ADDITIONAL_DATA
658 if no_children:
659 select_flags |= dnsserver.DNS_RPC_VIEW_NO_CHILDREN
660 if only_children:
661 select_flags |= dnsserver.DNS_RPC_VIEW_ONLY_CHILDREN
663 if select_flags == 0:
664 select_flags = dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
666 if select_flags == dnsserver.DNS_RPC_VIEW_ADDITIONAL_DATA:
667 self.outf.write('Specify either --authority or --root along with --additional.\n')
668 self.outf.write('Assuming --authority.\n')
669 select_flags |= dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
671 self.lp = sambaopts.get_loadparm()
672 self.creds = credopts.get_credentials(self.lp)
673 dns_conn = dns_connect(server, self.lp, self.creds)
675 buflen, res = dns_conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
677 server,
678 zone,
679 name,
680 None,
681 record_type,
682 select_flags,
683 None,
684 None)
685 print_dnsrecords(self.outf, res)
688 class cmd_roothints(Command):
689 """Query root hints"""
691 synopsis = '%prog <server> [<name>] [options]'
693 takes_args = [ 'server', 'name?' ]
695 def run(self, server, name='.', sambaopts=None, credopts=None, versionopts=None):
696 record_type = dnsp.DNS_TYPE_NS
697 select_flags = (dnsserver.DNS_RPC_VIEW_ROOT_HINT_DATA |
698 dnsserver.DNS_RPC_VIEW_ADDITIONAL_DATA)
700 self.lp = sambaopts.get_loadparm()
701 self.creds = credopts.get_credentials(self.lp)
702 dns_conn = dns_connect(server, self.lp, self.creds)
704 buflen, res = dns_conn.DnssrvEnumRecords2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
706 server,
707 '..RootHints',
708 name,
709 None,
710 record_type,
711 select_flags,
712 None,
713 None)
714 print_dnsrecords(self.outf, res)
717 class cmd_add_record(Command):
718 """Add a DNS record"""
720 synopsis = '%prog <server> <zone> <name> <A|AAAA|CNAME|NS> <data>'
722 takes_args = [ 'server', 'zone', 'name', 'rtype', 'data' ]
724 def run(self, server, zone, name, rtype, data, sambaopts=None, credopts=None, versionopts=None):
726 record_type = dns_type_flag(rtype)
728 if record_type == dnsp.DNS_TYPE_A:
729 rec = ARecord(data)
730 elif record_type == dnsp.DNS_TYPE_AAAA:
731 rec = AAAARecord(data)
732 elif record_type == dnsp.DNS_TYPE_CNAME:
733 rec = CNameRecord(data)
734 elif record_type == dnsp.DNS_TYPE_NS:
735 rec = NSRecord(data)
736 else:
737 raise CommandError('Adding record of type %s is not supported' % rtype)
739 self.lp = sambaopts.get_loadparm()
740 self.creds = credopts.get_credentials(self.lp)
741 dns_conn = dns_connect(server, self.lp, self.creds)
743 rec_match = dns_record_match(dns_conn, server, zone, name, record_type, data)
744 if rec_match is not None:
745 raise CommandError('Record already exists')
747 add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
748 add_rec_buf.rec = rec
750 dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
752 server,
753 zone,
754 name,
755 add_rec_buf,
756 None)
757 self.outf.write('Record added succefully\n')
760 class cmd_update_record(Command):
761 """Update a DNS record"""
763 synopsis = '%prog <server> <zone> <name> <A|AAAA|CNAME|NS> <olddata> <newdata>'
765 takes_args = [ 'server', 'zone', 'name', 'rtype', 'olddata', 'newdata' ]
767 def run(self, server, zone, name, rtype, olddata, newdata,
768 sambaopts=None, credopts=None, versionopts=None):
770 record_type = dns_type_flag(rtype)
771 if record_type == dnsp.DNS_TYPE_A:
772 rec = ARecord(newdata)
773 elif record_type == dnsp.DNS_TYPE_AAAA:
774 rec = AAAARecord(newdata)
775 elif record_type == dnsp.DNS_TYPE_CNAME:
776 rec = CNameRecord(newdata)
777 elif record_type == dnsp.DNS_TYPE_NS:
778 rec = NSRecord(newdata)
779 else:
780 raise CommandError('Updating record of type %s is not supported' % rtype)
782 self.lp = sambaopts.get_loadparm()
783 self.creds = credopts.get_credentials(self.lp)
784 dns_conn = dns_connect(server, self.lp, self.creds)
786 rec_match = dns_record_match(dns_conn, server, zone, name, record_type, olddata)
787 if not rec_match:
788 raise CommandError('Record does not exist')
790 # Copy properties from existing record to new record
791 rec.dwFlags = rec_match.dwFlags
792 rec.dwSerial = rec_match.dwSerial
793 rec.dwTtlSeconds = rec_match.dwTtlSeconds
794 rec.dwTimeStamp = rec_match.dwTimeStamp
796 add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
797 add_rec_buf.rec = rec
799 del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
800 del_rec_buf.rec = rec_match
802 dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
804 server,
805 zone,
806 name,
807 add_rec_buf,
808 del_rec_buf)
809 self.outf.write('Record updated succefully\n')
812 class cmd_delete_record(Command):
813 """Delete a DNS record"""
815 synopsis = '%prog <server> <zone> <name> <A|AAAA|CNAME|NS> <data>'
817 takes_args = [ 'server', 'zone', 'name', 'rtype', 'data' ]
819 def run(self, server, zone, name, rtype, data, sambaopts=None, credopts=None, versionopts=None):
821 record_type = dns_type_flag(rtype)
823 if record_type == dnsp.DNS_TYPE_A:
824 rec = ARecord(data)
825 elif record_type == dnsp.DNS_TYPE_AAAA:
826 rec = AAAARecord(data)
827 elif record_type == dnsp.DNS_TYPE_CNAME:
828 rec = CNameRecord(data)
829 elif record_type == dnsp.DNS_TYPE_NS:
830 rec = NSRecord(data)
831 else:
832 raise CommandError('Deleting record of type %s is not supported' % rtype)
834 self.lp = sambaopts.get_loadparm()
835 self.creds = credopts.get_credentials(self.lp)
836 dns_conn = dns_connect(server, self.lp, self.creds)
838 rec_match = dns_record_match(dns_conn, server, zone, name, record_type, data)
839 if not rec_match:
840 raise CommandError('Record does not exist')
842 del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
843 del_rec_buf.rec = rec_match
845 dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
847 server,
848 zone,
849 name,
850 None,
851 del_rec_buf)
852 self.outf.write('Record deleted succefully\n')
855 class cmd_dns(SuperCommand):
856 """Domain Name Service (DNS) management"""
858 subcommands = {}
859 subcommands['serverinfo'] = cmd_serverinfo()
860 subcommands['zoneinfo'] = cmd_zoneinfo()
861 subcommands['zonelist'] = cmd_zonelist()
862 subcommands['query'] = cmd_query()
863 subcommands['roothints'] = cmd_roothints()
864 subcommands['add'] = cmd_add_record()
865 subcommands['update'] = cmd_update_record()
866 subcommands['delete'] = cmd_delete_record()