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 struct
import pack
21 from socket
import inet_ntoa
24 from samba
.netcmd
import (
30 from samba
.dcerpc
import dnsp
, dnsserver
33 def dns_connect(server
, lp
, creds
):
34 if server
.lower() == 'localhost':
36 binding_str
= "ncacn_ip_tcp:%s[sign]" % server
37 dns_conn
= dnsserver
.dnsserver(binding_str
, lp
, creds
)
41 def bool_string(flag
):
47 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
62 def bitmap_string(module
, bitmap_defs
, value
):
65 if value
& getattr(module
, b
):
72 def boot_method_string(boot_method
):
73 enum_defs
= [ 'DNS_BOOT_METHOD_UNINITIALIZED', 'DNS_BOOT_METHOD_FILE',
74 'DNS_BOOT_METHOD_REGISTRY', 'DNS_BOOT_METHOD_DIRECTORY' ]
75 return enum_string(dnsserver
, enum_defs
, boot_method
)
78 def name_check_flag_string(check_flag
):
79 enum_defs
= [ 'DNS_ALLOW_RFC_NAMES_ONLY', 'DNS_ALLOW_NONRFC_NAMES',
80 'DNS_ALLOW_MULTIBYTE_NAMES', 'DNS_ALLOW_ALL_NAMES' ]
81 return enum_string(dnsserver
, enum_defs
, check_flag
)
84 def zone_type_string(zone_type
):
85 enum_defs
= [ 'DNS_ZONE_TYPE_CACHE', 'DNS_ZONE_TYPE_PRIMARY',
86 'DNS_ZONE_TYPE_SECONDARY', 'DNS_ZONE_TYPE_STUB',
87 'DNS_ZONE_TYPE_FORWARDER', 'DNS_ZONE_TYPE_SECONDARY_CACHE' ]
88 return enum_string(dnsp
, enum_defs
, zone_type
)
91 def zone_update_string(zone_update
):
92 enum_defs
= [ 'DNS_ZONE_UPDATE_OFF', 'DNS_ZONE_UPDATE_SECURE',
93 'DNS_ZONE_UPDATE_SECURE' ]
94 return enum_string(dnsp
, enum_defs
, zone_update
)
97 def zone_secondary_security_string(security
):
98 enum_defs
= [ 'DNS_ZONE_SECSECURE_NO_SECURITY', 'DNS_ZONE_SECSECURE_NS_ONLY',
99 'DNS_ZONE_SECSECURE_LIST_ONLY', 'DNS_ZONE_SECSECURE_NO_XFER' ]
100 return enum_string(dnsserver
, enum_defs
, security
)
103 def zone_notify_level_string(notify_level
):
104 enum_defs
= [ 'DNS_ZONE_NOTIFY_OFF', 'DNS_ZONE_NOTIFY_ALL_SECONDARIES',
105 'DNS_ZONE_NOTIFY_LIST_ONLY' ]
106 return enum_string(dnsserver
, enum_defs
, notify_level
)
109 def dp_flags_string(dp_flags
):
110 bitmap_defs
= [ 'DNS_DP_AUTOCREATED', 'DNS_DP_LEGACY', 'DNS_DP_DOMAIN_DEFAULT',
111 'DNS_DP_FOREST_DEFAULT', 'DNS_DP_ENLISTED', 'DNS_DP_DELETED' ]
112 return bitmap_string(dnsserver
, bitmap_defs
, dp_flags
)
115 def zone_flags_string(flags
):
116 bitmap_defs
= [ 'DNS_RPC_ZONE_PAUSED', 'DNS_RPC_ZONE_SHUTDOWN',
117 'DNS_RPC_ZONE_REVERSE', 'DNS_RPC_ZONE_AUTOCREATED',
118 'DNS_RPC_ZONE_DSINTEGRATED', 'DNS_RPC_ZONE_AGING',
119 'DNS_RPC_ZONE_UPDATE_UNSECURE', 'DNS_RPC_ZONE_UPDATE_SECURE',
120 'DNS_RPC_ZONE_READONLY']
121 return bitmap_string(dnsserver
, bitmap_defs
, flags
)
124 def ip4_array_string(array
):
128 for i
in xrange(array
.AddrCount
):
129 addr
= '%s' % inet_ntoa(pack('i', array
.AddrArray
[i
]))
134 def dns_addr_array_string(array
):
138 for i
in xrange(array
.AddrCount
):
139 if array
.AddrArray
[i
].MaxSa
[0] == 0x02:
140 addr
= '%d.%d.%d.%d (%d)' % \
141 tuple(array
.AddrArray
[i
].MaxSa
[4:8] + [array
.AddrArray
[i
].MaxSa
[3]])
142 elif array
.AddrArray
[i
].MaxSa
[0] == 0x17:
143 addr
= '%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x (%d)' % \
144 tuple(array
.AddrArray
[i
].MaxSa
[4:20] + [array
.AddrArray
[i
].MaxSa
[3]])
151 def dns_type_flag(rec_type
):
152 rtype
= rec_type
.upper()
154 record_type
= dnsp
.DNS_TYPE_A
155 elif rtype
== 'AAAA':
156 record_type
= dnsp
.DNS_TYPE_AAAA
158 record_type
= dnsp
.DNS_TYPE_PTR
160 record_type
= dnsp
.DNS_TYPE_NS
161 elif rtype
== 'CNAME':
162 record_type
= dnsp
.DNS_TYPE_CNAME
164 record_type
= dnsp
.DNS_TYPE_SOA
166 record_type
= dnsp
.DNS_TYPE_MX
168 record_type
= dnsp
.DNS_TYPE_SRV
170 record_type
= dnsp
.DNS_TYPE_TXT
172 record_type
= dnsp
.DNS_TYPE_ALL
174 raise CommandError('Unknown type of DNS record %s' % rec_type
)
178 def dns_client_version(cli_version
):
179 version
= cli_version
.upper()
181 client_version
= dnsserver
.DNS_CLIENT_VERSION_W2K
182 elif version
== 'DOTNET':
183 client_version
= dnsserver
.DNS_CLIENT_VERSION_DOTNET
184 elif version
== 'LONGHORN':
185 client_version
= dnsserver
.DNS_CLIENT_VERSION_LONGHORN
187 raise CommandError('Unknown client version %s' % cli_version
)
188 return client_version
191 def print_serverinfo(outf
, typeid
, serverinfo
):
192 outf
.write(' dwVersion : 0x%x\n' % serverinfo
.dwVersion
)
193 outf
.write(' fBootMethod : %s\n' % boot_method_string(serverinfo
.fBootMethod
))
194 outf
.write(' fAdminConfigured : %s\n' % bool_string(serverinfo
.fAdminConfigured
))
195 outf
.write(' fAllowUpdate : %s\n' % bool_string(serverinfo
.fAllowUpdate
))
196 outf
.write(' fDsAvailable : %s\n' % bool_string(serverinfo
.fDsAvailable
))
197 outf
.write(' pszServerName : %s\n' % serverinfo
.pszServerName
)
198 outf
.write(' pszDsContainer : %s\n' % serverinfo
.pszDsContainer
)
200 if typeid
!= dnsserver
.DNSSRV_TYPEID_SERVER_INFO
:
201 outf
.write(' aipServerAddrs : %s\n' %
202 ip4_array_string(serverinfo
.aipServerAddrs
))
203 outf
.write(' aipListenAddrs : %s\n' %
204 ip4_array_string(serverinfo
.aipListenAddrs
))
205 outf
.write(' aipForwarders : %s\n' %
206 ip4_array_string(serverinfo
.aipForwarders
))
208 outf
.write(' aipServerAddrs : %s\n' %
209 dns_addr_array_string(serverinfo
.aipServerAddrs
))
210 outf
.write(' aipListenAddrs : %s\n' %
211 dns_addr_array_string(serverinfo
.aipListenAddrs
))
212 outf
.write(' aipForwarders : %s\n' %
213 dns_addr_array_string(serverinfo
.aipForwarders
))
215 outf
.write(' dwLogLevel : %d\n' % serverinfo
.dwLogLevel
)
216 outf
.write(' dwDebugLevel : %d\n' % serverinfo
.dwDebugLevel
)
217 outf
.write(' dwForwardTimeout : %d\n' % serverinfo
.dwForwardTimeout
)
218 outf
.write(' dwRpcPrototol : 0x%x\n' % serverinfo
.dwRpcProtocol
)
219 outf
.write(' dwNameCheckFlag : %s\n' % name_check_flag_string(serverinfo
.dwNameCheckFlag
))
220 outf
.write(' cAddressAnswerLimit : %d\n' % serverinfo
.cAddressAnswerLimit
)
221 outf
.write(' dwRecursionRetry : %d\n' % serverinfo
.dwRecursionRetry
)
222 outf
.write(' dwRecursionTimeout : %d\n' % serverinfo
.dwRecursionTimeout
)
223 outf
.write(' dwMaxCacheTtl : %d\n' % serverinfo
.dwMaxCacheTtl
)
224 outf
.write(' dwDsPollingInterval : %d\n' % serverinfo
.dwDsPollingInterval
)
225 outf
.write(' dwScavengingInterval : %d\n' % serverinfo
.dwScavengingInterval
)
226 outf
.write(' dwDefaultRefreshInterval : %d\n' % serverinfo
.dwDefaultRefreshInterval
)
227 outf
.write(' dwDefaultNoRefreshInterval : %d\n' % serverinfo
.dwDefaultNoRefreshInterval
)
228 outf
.write(' fAutoReverseZones : %s\n' % bool_string(serverinfo
.fAutoReverseZones
))
229 outf
.write(' fAutoCacheUpdate : %s\n' % bool_string(serverinfo
.fAutoCacheUpdate
))
230 outf
.write(' fRecurseAfterForwarding : %s\n' % bool_string(serverinfo
.fRecurseAfterForwarding
))
231 outf
.write(' fForwardDelegations : %s\n' % bool_string(serverinfo
.fForwardDelegations
))
232 outf
.write(' fNoRecursion : %s\n' % bool_string(serverinfo
.fNoRecursion
))
233 outf
.write(' fSecureResponses : %s\n' % bool_string(serverinfo
.fSecureResponses
))
234 outf
.write(' fRoundRobin : %s\n' % bool_string(serverinfo
.fRoundRobin
))
235 outf
.write(' fLocalNetPriority : %s\n' % bool_string(serverinfo
.fLocalNetPriority
))
236 outf
.write(' fBindSecondaries : %s\n' % bool_string(serverinfo
.fBindSecondaries
))
237 outf
.write(' fWriteAuthorityNs : %s\n' % bool_string(serverinfo
.fWriteAuthorityNs
))
238 outf
.write(' fStrictFileParsing : %s\n' % bool_string(serverinfo
.fStrictFileParsing
))
239 outf
.write(' fLooseWildcarding : %s\n' % bool_string(serverinfo
.fLooseWildcarding
))
240 outf
.write(' fDefaultAgingState : %s\n' % bool_string(serverinfo
.fDefaultAgingState
))
242 if typeid
!= dnsserver
.DNSSRV_TYPEID_SERVER_INFO_W2K
:
243 outf
.write(' dwRpcStructureVersion : 0x%x\n' % serverinfo
.dwRpcStructureVersion
)
244 outf
.write(' aipLogFilter : %s\n' % dns_addr_array_string(serverinfo
.aipLogFilter
))
245 outf
.write(' pwszLogFilePath : %s\n' % serverinfo
.pwszLogFilePath
)
246 outf
.write(' pszDomainName : %s\n' % serverinfo
.pszDomainName
)
247 outf
.write(' pszForestName : %s\n' % serverinfo
.pszForestName
)
248 outf
.write(' pszDomainDirectoryPartition : %s\n' % serverinfo
.pszDomainDirectoryPartition
)
249 outf
.write(' pszForestDirectoryPartition : %s\n' % serverinfo
.pszForestDirectoryPartition
)
251 outf
.write(' dwLocalNetPriorityNetMask : 0x%x\n' % serverinfo
.dwLocalNetPriorityNetMask
)
252 outf
.write(' dwLastScavengeTime : %d\n' % serverinfo
.dwLastScavengeTime
)
253 outf
.write(' dwEventLogLevel : %d\n' % serverinfo
.dwEventLogLevel
)
254 outf
.write(' dwLogFileMaxSize : %d\n' % serverinfo
.dwLogFileMaxSize
)
255 outf
.write(' dwDsForestVersion : %d\n' % serverinfo
.dwDsForestVersion
)
256 outf
.write(' dwDsDomainVersion : %d\n' % serverinfo
.dwDsDomainVersion
)
257 outf
.write(' dwDsDsaVersion : %d\n' % serverinfo
.dwDsDsaVersion
)
259 if typeid
== dnsserver
.DNSSRV_TYPEID_SERVER_INFO
:
260 outf
.write(' fReadOnlyDC : %s\n' % bool_string(serverinfo
.fReadOnlyDC
))
263 def print_zoneinfo(outf
, typeid
, zoneinfo
):
264 outf
.write(' pszZoneName : %s\n' % zoneinfo
.pszZoneName
)
265 outf
.write(' dwZoneType : %s\n' % zone_type_string(zoneinfo
.dwZoneType
))
266 outf
.write(' fReverse : %s\n' % bool_string(zoneinfo
.fReverse
))
267 outf
.write(' fAllowUpdate : %s\n' % zone_update_string(zoneinfo
.fAllowUpdate
))
268 outf
.write(' fPaused : %s\n' % bool_string(zoneinfo
.fPaused
))
269 outf
.write(' fShutdown : %s\n' % bool_string(zoneinfo
.fShutdown
))
270 outf
.write(' fAutoCreated : %s\n' % bool_string(zoneinfo
.fAutoCreated
))
271 outf
.write(' fUseDatabase : %s\n' % bool_string(zoneinfo
.fUseDatabase
))
272 outf
.write(' pszDataFile : %s\n' % zoneinfo
.pszDataFile
)
273 if typeid
!= dnsserver
.DNSSRV_TYPEID_ZONE_INFO
:
274 outf
.write(' aipMasters : %s\n' %
275 ip4_array_string(zoneinfo
.aipMasters
))
277 outf
.write(' aipMasters : %s\n' %
278 dns_addr_array_string(zoneinfo
.aipMasters
))
279 outf
.write(' fSecureSecondaries : %s\n' % zone_secondary_security_string(zoneinfo
.fSecureSecondaries
))
280 outf
.write(' fNotifyLevel : %s\n' % zone_notify_level_string(zoneinfo
.fNotifyLevel
))
281 if typeid
!= dnsserver
.DNSSRV_TYPEID_ZONE_INFO
:
282 outf
.write(' aipSecondaries : %s\n' %
283 ip4_array_string(zoneinfo
.aipSecondaries
))
284 outf
.write(' aipNotify : %s\n' %
285 ip4_array_string(zoneinfo
.aipNotify
))
287 outf
.write(' aipSecondaries : %s\n' %
288 dns_addr_array_string(zoneinfo
.aipSecondaries
))
289 outf
.write(' aipNotify : %s\n' %
290 dns_addr_array_string(zoneinfo
.aipNotify
))
291 outf
.write(' fUseWins : %s\n' % bool_string(zoneinfo
.fUseWins
))
292 outf
.write(' fUseNbstat : %s\n' % bool_string(zoneinfo
.fUseNbstat
))
293 outf
.write(' fAging : %s\n' % bool_string(zoneinfo
.fAging
))
294 outf
.write(' dwNoRefreshInterval : %d\n' % zoneinfo
.dwNoRefreshInterval
)
295 outf
.write(' dwRefreshInterval : %d\n' % zoneinfo
.dwRefreshInterval
)
296 outf
.write(' dwAvailForScavengeTime : %d\n' % zoneinfo
.dwAvailForScavengeTime
)
297 if typeid
!= dnsserver
.DNSSRV_TYPEID_ZONE_INFO
:
298 outf
.write(' aipScavengeServers : %s\n' %
299 ip4_array_string(zoneinfo
.aipScavengeServers
))
301 outf
.write(' aipScavengeServers : %s\n' %
302 dns_addr_array_string(zoneinfo
.aipScavengeServers
))
304 if typeid
!= dnsserver
.DNSSRV_TYPEID_ZONE_INFO_W2K
:
305 outf
.write(' dwRpcStructureVersion : 0x%x\n' % zoneinfo
.dwRpcStructureVersion
)
306 outf
.write(' dwForwarderTimeout : %d\n' % zoneinfo
.dwForwarderTimeout
)
307 outf
.write(' fForwarderSlave : %d\n' % zoneinfo
.fForwarderSlave
)
308 if typeid
!= dnsserver
.DNSSRV_TYPEID_ZONE_INFO
:
309 outf
.write(' aipLocalMasters : %s\n' %
310 ip4_array_string(zoneinfo
.aipLocalMasters
))
312 outf
.write(' aipLocalMasters : %s\n' %
313 dns_addr_array_string(zoneinfo
.aipLocalMasters
))
314 outf
.write(' dwDpFlags : %s\n' % dp_flags_string(zoneinfo
.dwDpFlags
))
315 outf
.write(' pszDpFqdn : %s\n' % zoneinfo
.pszDpFqdn
)
316 outf
.write(' pwszZoneDn : %s\n' % zoneinfo
.pwszZoneDn
)
317 outf
.write(' dwLastSuccessfulSoaCheck : %d\n' % zoneinfo
.dwLastSuccessfulSoaCheck
)
318 outf
.write(' dwLastSuccessfulXfr : %d\n' % zoneinfo
.dwLastSuccessfulXfr
)
320 if typeid
== dnsserver
.DNSSRV_TYPEID_ZONE_INFO
:
321 outf
.write(' fQueuedForBackgroundLoad : %s\n' % bool_string(zoneinfo
.fQueuedForBackgroundLoad
))
322 outf
.write(' fBackgroundLoadInProgress : %s\n' % bool_string(zoneinfo
.fBackgroundLoadInProgress
))
323 outf
.write(' fReadOnlyZone : %s\n' % bool_string(zoneinfo
.fReadOnlyZone
))
324 outf
.write(' dwLastXfrAttempt : %d\n' % zoneinfo
.dwLastXfrAttempt
)
325 outf
.write(' dwLastXfrResult : %d\n' % zoneinfo
.dwLastXfrResult
)
328 def print_zone(outf
, typeid
, zone
):
329 outf
.write(' pszZoneName : %s\n' % zone
.pszZoneName
)
330 outf
.write(' Flags : %s\n' % zone_flags_string(zone
.Flags
))
331 outf
.write(' ZoneType : %s\n' % zone_type_string(zone
.ZoneType
))
332 outf
.write(' Version : %s\n' % zone
.Version
)
334 if typeid
!= dnsserver
.DNSSRV_TYPEID_ZONE_W2K
:
335 outf
.write(' dwDpFlags : %s\n' % dp_flags_string(zone
.dwDpFlags
))
336 outf
.write(' pszDpFqdn : %s\n' % zone
.pszDpFqdn
)
339 def print_enumzones(outf
, typeid
, zones
):
340 outf
.write(' %d zone(s) found\n' % zones
.dwZoneCount
)
341 for zone
in zones
.ZoneArray
:
343 print_zone(outf
, typeid
, zone
)
346 def print_dns_record(outf
, rec
):
347 if rec
.wType
== dnsp
.DNS_TYPE_A
:
348 mesg
= 'A: %s' % (rec
.data
)
349 elif rec
.wType
== dnsp
.DNS_TYPE_AAAA
:
350 mesg
= 'AAAA: %s' % (rec
.data
)
351 elif rec
.wType
== dnsp
.DNS_TYPE_PTR
:
352 mesg
= 'PTR: %s' % (rec
.data
.str)
353 elif rec
.wType
== dnsp
.DNS_TYPE_NS
:
354 mesg
= 'NS: %s' % (rec
.data
.str)
355 elif rec
.wType
== dnsp
.DNS_TYPE_CNAME
:
356 mesg
= 'CNAME: %s' % (rec
.data
.str)
357 elif rec
.wType
== dnsp
.DNS_TYPE_SOA
:
358 mesg
= 'SOA: serial=%d, refresh=%d, retry=%d, expire=%d, ns=%s, email=%s' % (
363 rec
.data
.NamePrimaryServer
.str,
364 rec
.data
.ZoneAdministratorEmail
.str)
365 elif rec
.wType
== dnsp
.DNS_TYPE_MX
:
366 mesg
= 'MX: %s (%d)' % (rec
.data
.nameExchange
.str, rec
.data
.wPreference
)
367 elif rec
.wType
== dnsp
.DNS_TYPE_SRV
:
368 mesg
= 'SRV: %s (%d, %d, %d)' % (rec
.data
.nameTarget
.str, rec
.data
.wPort
,
369 rec
.data
.wPriority
, rec
.data
.wWeight
)
370 elif rec
.wType
== dnsp
.DNS_TYPE_TXT
:
371 slist
= ['"%s"' % name
.str for name
in rec
.data
.str]
372 mesg
= 'TXT: %s' % ','.join(slist
)
375 outf
.write(' %s (flags=%x, serial=%d, ttl=%d)\n' % (
376 mesg
, rec
.dwFlags
, rec
.dwSerial
, rec
.dwTtlSeconds
))
379 def print_dnsrecords(outf
, records
):
380 for rec
in records
.rec
:
381 outf
.write(' Name=%s, Records=%d, Children=%d\n' % (
385 for dns_rec
in rec
.records
:
386 print_dns_record(outf
, dns_rec
)
390 # Always create a copy of strings when creating DNS_RPC_RECORDs
391 # to overcome the bug in pidl generated python bindings.
394 class ARecord(dnsserver
.DNS_RPC_RECORD
):
395 def __init__(self
, ip_addr
, serial
=1, ttl
=900, rank
=dnsp
.DNS_RANK_ZONE
,
397 super(ARecord
, self
).__init
__()
398 self
.wType
= dnsp
.DNS_TYPE_A
399 self
.dwFlags
= rank | node_flag
400 self
.dwSerial
= serial
401 self
.dwTtlSeconds
= ttl
402 self
._ip
_addr
= ip_addr
[:]
403 self
.data
= self
._ip
_addr
406 class AAAARecord(dnsserver
.DNS_RPC_RECORD
):
408 def __init__(self
, ip6_addr
, serial
=1, ttl
=900, rank
=dnsp
.DNS_RANK_ZONE
,
410 super(AAAARecord
, self
).__init
__()
411 self
.wType
= dnsp
.DNS_TYPE_AAAA
412 self
.dwFlags
= rank | node_flag
413 self
.dwSerial
= serial
414 self
.dwTtlSeconds
= ttl
415 self
._ip
6_addr
= ip6_addr
[:]
416 self
.data
= self
._ip
6_addr
419 class PTRRecord(dnsserver
.DNS_RPC_RECORD
):
421 def __init__(self
, ptr
, serial
=1, ttl
=900, rank
=dnsp
.DNS_RANK_ZONE
,
423 super(PTRRecord
, self
).__init
__()
424 self
.wType
= dnsp
.DNS_TYPE_PTR
425 self
.dwFlags
= rank | node_flag
426 self
.dwSerial
= serial
427 self
.dwTtleSeconds
= ttl
429 ptr_name
= dnsserver
.DNS_RPC_NAME()
430 ptr_name
.str = self
._ptr
431 ptr_name
.len = len(ptr
)
435 class CNameRecord(dnsserver
.DNS_RPC_RECORD
):
437 def __init__(self
, cname
, serial
=1, ttl
=900, rank
=dnsp
.DNS_RANK_ZONE
,
439 super(CNameRecord
, self
).__init
__()
440 self
.wType
= dnsp
.DNS_TYPE_CNAME
441 self
.dwFlags
= rank | node_flag
442 self
.dwSerial
= serial
443 self
.dwTtlSeconds
= ttl
444 self
._cname
= cname
[:]
445 cname_name
= dnsserver
.DNS_RPC_NAME()
446 cname_name
.str = self
._cname
447 cname_name
.len = len(cname
)
448 self
.data
= cname_name
451 class NSRecord(dnsserver
.DNS_RPC_RECORD
):
453 def __init__(self
, dns_server
, serial
=1, ttl
=900, rank
=dnsp
.DNS_RANK_ZONE
,
455 super(NSRecord
, self
).__init
__()
456 self
.wType
= dnsp
.DNS_TYPE_NS
457 self
.dwFlags
= rank | node_flag
458 self
.dwSerial
= serial
459 self
.dwTtlSeconds
= ttl
460 self
._dns
_server
= dns_server
[:]
461 ns
= dnsserver
.DNS_RPC_NAME()
462 ns
.str = self
._dns
_server
463 ns
.len = len(dns_server
)
467 class MXRecord(dnsserver
.DNS_RPC_RECORD
):
469 def __init__(self
, mail_server
, preference
, serial
=1, ttl
=900,
470 rank
=dnsp
.DNS_RANK_ZONE
, node_flag
=0):
471 super(MXRecord
, self
).__init
__()
472 self
.wType
= dnsp
.DNS_TYPE_MX
473 self
.dwFlags
= rank | node_flag
474 self
.dwSerial
= serial
475 self
.dwTtlSeconds
= ttl
476 self
._mail
_server
= mail_server
[:]
477 mx
= dnsserver
.DNS_RPC_RECORD_NAME_PREFERENCE()
478 mx
.wPreference
= preference
479 mx
.nameExchange
.str = self
._mail
_server
480 mx
.nameExchange
.len = len(mail_server
)
484 class SOARecord(dnsserver
.DNS_RPC_RECORD
):
486 def __init__(self
, mname
, rname
, serial
=1, refresh
=900, retry
=600,
487 expire
=86400, minimum
=3600, ttl
=3600, rank
=dnsp
.DNS_RANK_ZONE
,
488 node_flag
=dnsp
.DNS_RPC_FLAG_AUTH_ZONE_ROOT
):
489 super(SOARecord
, self
).__init
__()
490 self
.wType
= dnsp
.DNS_TYPE_SOA
491 self
.dwFlags
= rank | node_flag
492 self
.dwSerial
= serial
493 self
.dwTtlSeconds
= ttl
494 self
._mname
= mname
[:]
495 self
._rname
= rname
[:]
496 soa
= dnsserver
.DNS_RPC_RECORD_SOA()
497 soa
.dwSerialNo
= serial
498 soa
.dwRefresh
= refresh
500 soa
.dwExpire
= expire
501 soa
.NamePrimaryServer
.str = self
._mname
502 soa
.NamePrimaryServer
.len = len(mname
)
503 soa
.ZoneAdministratorEmail
.str = self
._rname
504 soa
.ZoneAdministratorEmail
.len = len(rname
)
508 class SRVRecord(dnsserver
.DNS_RPC_RECORD
):
510 def __init__(self
, target
, port
, priority
=0, weight
=100, serial
=1, ttl
=900,
511 rank
=dnsp
.DNS_RANK_ZONE
, node_flag
=0):
512 super(SRVRecord
, self
).__init
__()
513 self
.wType
= dnsp
.DNS_TYPE_SRV
514 self
.dwFlags
= rank | node_flag
515 self
.dwSerial
= serial
516 self
.dwTtlSeconds
= ttl
517 self
._target
= target
[:]
518 srv
= dnsserver
.DNS_RPC_RECORD_SRV()
519 srv
.wPriority
= priority
522 srv
.nameTarget
.str = self
._target
523 srv
.nameTarget
.len = len(target
)
527 class TXTRecord(dnsserver
.DNS_RPC_RECORD
):
529 def __init__(self
, slist
, serial
=1, ttl
=900, rank
=dnsp
.DNS_RANK_ZONE
,
531 super(TXTRecord
, self
).__init
__()
532 self
.wType
= dnsp
.DNS_TYPE_TXT
533 self
.dwFlags
= rank | node_flag
534 self
.dwSerial
= serial
535 self
.dwTtlSeconds
= ttl
538 self
._slist
.append(s
[:])
540 for s
in self
._slist
:
541 name
= dnsserver
.DNS_RPC_NAME()
545 txt
= dnsserver
.DNS_RPC_RECORD_STRING()
546 txt
.count
= len(slist
)
551 # Convert data into a dns record
552 def data_to_dns_record(record_type
, data
):
553 if record_type
== dnsp
.DNS_TYPE_A
:
555 elif record_type
== dnsp
.DNS_TYPE_AAAA
:
556 rec
= AAAARecord(data
)
557 elif record_type
== dnsp
.DNS_TYPE_PTR
:
558 rec
= PTRRecord(data
)
559 elif record_type
== dnsp
.DNS_TYPE_CNAME
:
560 rec
= CNameRecord(data
)
561 elif record_type
== dnsp
.DNS_TYPE_NS
:
563 elif record_type
== dnsp
.DNS_TYPE_MX
:
564 tmp
= data
.split(' ')
566 raise CommandError('Data requires 2 elements - mail_server, preference')
568 preference
= int(tmp
[1])
569 rec
= MXRecord(mail_server
, preference
)
570 elif record_type
== dnsp
.DNS_TYPE_SRV
:
571 tmp
= data
.split(' ')
573 raise CommandError('Data requires 4 elements - server, port, priority, weight')
576 priority
= int(tmp
[2])
578 rec
= SRVRecord(server
, port
, priority
=priority
, weight
=weight
)
579 elif record_type
== dnsp
.DNS_TYPE_SOA
:
580 tmp
= data
.split(' ')
582 raise CommandError('Data requires 7 elements - nameserver, email, serial, '
583 'refresh, retry, expire, minimumttl')
587 refresh
= int(tmp
[3])
590 minimum
= int(tmp
[6])
591 rec
= SOARecord(nameserver
, email
, serial
=serial
, refresh
=refresh
,
592 retry
=retry
, expire
=expire
, minimum
=minimum
)
593 elif record_type
== dnsp
.DNS_TYPE_TXT
:
594 slist
= shlex
.split(data
)
595 rec
= TXTRecord(slist
)
597 raise CommandError('Unsupported record type')
601 # Match dns name (of type DNS_RPC_NAME)
602 def dns_name_equal(n1
, n2
):
603 return n1
.str.rstrip('.').lower() == n2
.str.rstrip('.').lower()
606 # Match a dns record with specified data
607 def dns_record_match(dns_conn
, server
, zone
, name
, record_type
, data
):
608 urec
= data_to_dns_record(record_type
, data
)
610 select_flags
= dnsserver
.DNS_RPC_VIEW_AUTHORITY_DATA
613 buflen
, res
= dns_conn
.DnssrvEnumRecords2(
614 dnsserver
.DNS_CLIENT_VERSION_LONGHORN
, 0, server
, zone
, name
, None,
615 record_type
, select_flags
, None, None)
616 except RuntimeError, e
:
619 if not res
or res
.count
== 0:
623 for rec
in res
.rec
[0].records
:
624 if rec
.wType
!= record_type
:
628 if record_type
== dnsp
.DNS_TYPE_A
:
629 if rec
.data
== urec
.data
:
631 elif record_type
== dnsp
.DNS_TYPE_AAAA
:
632 if rec
.data
== urec
.data
:
634 elif record_type
== dnsp
.DNS_TYPE_PTR
:
635 if dns_name_equal(rec
.data
, urec
.data
):
637 elif record_type
== dnsp
.DNS_TYPE_CNAME
:
638 if dns_name_equal(rec
.data
, urec
.data
):
640 elif record_type
== dnsp
.DNS_TYPE_NS
:
641 if dns_name_equal(rec
.data
, urec
.data
):
643 elif record_type
== dnsp
.DNS_TYPE_MX
:
644 if dns_name_equal(rec
.data
.nameExchange
, urec
.data
.nameExchange
) and \
645 rec
.data
.wPreference
== urec
.data
.wPreference
:
647 elif record_type
== dnsp
.DNS_TYPE_SRV
:
648 if rec
.data
.wPriority
== urec
.data
.wPriority
and \
649 rec
.data
.wWeight
== urec
.data
.wWeight
and \
650 rec
.data
.wPort
== urec
.data
.wPort
and \
651 dns_name_equal(rec
.data
.nameTarget
, urec
.data
.nameTarget
):
653 elif record_type
== dnsp
.DNS_TYPE_SOA
:
654 if rec
.data
.dwSerialNo
== urec
.data
.dwSerialNo
and \
655 rec
.data
.dwRefresh
== urec
.data
.dwRefresh
and \
656 rec
.data
.dwRetry
== urec
.data
.dwRetry
and \
657 rec
.data
.dwExpire
== urec
.data
.dwExpire
and \
658 rec
.data
.dwMinimumTtl
== urec
.data
.dwMinimumTtl
and \
659 dns_name_equal(rec
.data
.NamePrimaryServer
,
660 urec
.data
.NamePrimaryServer
) and \
661 dns_name_equal(rec
.data
.ZoneAdministratorEmail
,
662 urec
.data
.ZoneAdministratorEmail
):
664 elif record_type
== dnsp
.DNS_TYPE_TXT
:
665 if rec
.data
.count
== urec
.data
.count
:
667 for i
in xrange(rec
.data
.count
):
669 (rec
.data
.str[i
].str == urec
.data
.str[i
].str)
678 class cmd_serverinfo(Command
):
679 """Query for Server information."""
681 synopsis
= '%prog <server> [options]'
683 takes_args
= [ 'server' ]
685 takes_optiongroups
= {
686 "sambaopts": options
.SambaOptions
,
687 "versionopts": options
.VersionOptions
,
688 "credopts": options
.CredentialsOptions
,
692 Option('--client-version', help='Client Version',
693 default
='longhorn', metavar
='w2k|dotnet|longhorn',
694 choices
=['w2k','dotnet','longhorn'], dest
='cli_ver'),
697 def run(self
, server
, cli_ver
, sambaopts
=None, credopts
=None,
699 self
.lp
= sambaopts
.get_loadparm()
700 self
.creds
= credopts
.get_credentials(self
.lp
)
701 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
703 client_version
= dns_client_version(cli_ver
)
705 typeid
, res
= dns_conn
.DnssrvQuery2(client_version
, 0, server
,
707 print_serverinfo(self
.outf
, typeid
, res
)
710 class cmd_zoneinfo(Command
):
711 """Query for zone information."""
713 synopsis
= '%prog <server> <zone> [options]'
715 takes_args
= [ 'server', 'zone' ]
717 takes_optiongroups
= {
718 "sambaopts": options
.SambaOptions
,
719 "versionopts": options
.VersionOptions
,
720 "credopts": options
.CredentialsOptions
,
724 Option('--client-version', help='Client Version',
725 default
='longhorn', metavar
='w2k|dotnet|longhorn',
726 choices
=['w2k','dotnet','longhorn'], dest
='cli_ver'),
729 def run(self
, server
, zone
, cli_ver
, sambaopts
=None, credopts
=None,
731 self
.lp
= sambaopts
.get_loadparm()
732 self
.creds
= credopts
.get_credentials(self
.lp
)
733 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
735 client_version
= dns_client_version(cli_ver
)
737 typeid
, res
= dns_conn
.DnssrvQuery2(client_version
, 0, server
, zone
,
739 print_zoneinfo(self
.outf
, typeid
, res
)
742 class cmd_zonelist(Command
):
743 """Query for zones."""
745 synopsis
= '%prog <server> [options]'
747 takes_args
= [ 'server' ]
749 takes_optiongroups
= {
750 "sambaopts": options
.SambaOptions
,
751 "versionopts": options
.VersionOptions
,
752 "credopts": options
.CredentialsOptions
,
756 Option('--client-version', help='Client Version',
757 default
='longhorn', metavar
='w2k|dotnet|longhorn',
758 choices
=['w2k','dotnet','longhorn'], dest
='cli_ver'),
759 Option('--primary', help='List primary zones (default)',
760 action
='store_true', dest
='primary'),
761 Option('--secondary', help='List secondary zones',
762 action
='store_true', dest
='secondary'),
763 Option('--cache', help='List cached zones',
764 action
='store_true', dest
='cache'),
765 Option('--auto', help='List automatically created zones',
766 action
='store_true', dest
='auto'),
767 Option('--forward', help='List forward zones',
768 action
='store_true', dest
='forward'),
769 Option('--reverse', help='List reverse zones',
770 action
='store_true', dest
='reverse'),
771 Option('--ds', help='List directory integrated zones',
772 action
='store_true', dest
='ds'),
773 Option('--non-ds', help='List non-directory zones',
774 action
='store_true', dest
='nonds')
777 def run(self
, server
, cli_ver
, primary
=False, secondary
=False, cache
=False,
778 auto
=False, forward
=False, reverse
=False, ds
=False, nonds
=False,
779 sambaopts
=None, credopts
=None, versionopts
=None):
783 request_filter |
= dnsserver
.DNS_ZONE_REQUEST_PRIMARY
785 request_filter |
= dnsserver
.DNS_ZONE_REQUEST_SECONDARY
787 request_filter |
= dnsserver
.DNS_ZONE_REQUEST_CACHE
789 request_filter |
= dnsserver
.DNS_ZONE_REQUEST_AUTO
791 request_filter |
= dnsserver
.DNS_ZONE_REQUEST_FORWARD
793 request_filter |
= dnsserver
.DNS_ZONE_REQUEST_REVERSE
795 request_filter |
= dnsserver
.DNS_ZONE_REQUEST_DS
797 request_filter |
= dnsserver
.DNS_ZONE_REQUEST_NON_DS
799 if request_filter
== 0:
800 request_filter
= dnsserver
.DNS_ZONE_REQUEST_PRIMARY
802 self
.lp
= sambaopts
.get_loadparm()
803 self
.creds
= credopts
.get_credentials(self
.lp
)
804 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
806 client_version
= dns_client_version(cli_ver
)
808 typeid
, res
= dns_conn
.DnssrvComplexOperation2(client_version
,
811 dnsserver
.DNSSRV_TYPEID_DWORD
,
814 if client_version
== dnsserver
.DNS_CLIENT_VERSION_W2K
:
815 typeid
= dnsserver
.DNSSRV_TYPEID_ZONE_W2K
817 typeid
= dnsserver
.DNSSRV_TYPEID_ZONE
818 print_enumzones(self
.outf
, typeid
, res
)
821 class cmd_zonecreate(Command
):
824 synopsis
= '%prog <server> <zone> [options]'
826 takes_args
= [ 'server', 'zone' ]
828 takes_optiongroups
= {
829 "sambaopts": options
.SambaOptions
,
830 "versionopts": options
.VersionOptions
,
831 "credopts": options
.CredentialsOptions
,
835 Option('--client-version', help='Client Version',
836 default
='longhorn', metavar
='w2k|dotnet|longhorn',
837 choices
=['w2k','dotnet','longhorn'], dest
='cli_ver')
840 def run(self
, server
, zone
, cli_ver
, sambaopts
=None, credopts
=None,
843 self
.lp
= sambaopts
.get_loadparm()
844 self
.creds
= credopts
.get_credentials(self
.lp
)
845 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
849 client_version
= dns_client_version(cli_ver
)
850 if client_version
== dnsserver
.DNS_CLIENT_VERSION_W2K
:
851 typeid
= dnsserver
.DNSSRV_TYPEID_ZONE_CREATE_W2K
852 zone_create_info
= dnsserver
.DNS_RPC_ZONE_CREATE_INFO_W2K()
853 zone_create_info
.pszZoneName
= zone
854 zone_create_info
.dwZoneType
= dnsp
.DNS_ZONE_TYPE_PRIMARY
855 zone_create_info
.fAllowUpdate
= dnsp
.DNS_ZONE_UPDATE_SECURE
856 zone_create_info
.fAging
= 0
857 elif client_version
== dnsserver
.DNS_CLIENT_VERSION_DOTNET
:
858 typeid
= dnsserver
.DNSSRV_TYPEID_ZONE_CREATE_DOTNET
859 zone_create_info
= dnsserver
.DNS_RPC_ZONE_CREATE_INFO_DOTNET()
860 zone_create_info
.pszZoneName
= zone
861 zone_create_info
.dwZoneType
= dnsp
.DNS_ZONE_TYPE_PRIMARY
862 zone_create_info
.fAllowUpdate
= dnsp
.DNS_ZONE_UPDATE_SECURE
863 zone_create_info
.fAging
= 0
864 zone_create_info
.dwDpFlags
= dnsserver
.DNS_DP_DOMAIN_DEFAULT
866 typeid
= dnsserver
.DNSSRV_TYPEID_ZONE_CREATE
867 zone_create_info
= dnsserver
.DNS_RPC_ZONE_CREATE_INFO_LONGHORN()
868 zone_create_info
.pszZoneName
= zone
869 zone_create_info
.dwZoneType
= dnsp
.DNS_ZONE_TYPE_PRIMARY
870 zone_create_info
.fAllowUpdate
= dnsp
.DNS_ZONE_UPDATE_SECURE
871 zone_create_info
.fAging
= 0
872 zone_create_info
.dwDpFlags
= dnsserver
.DNS_DP_DOMAIN_DEFAULT
874 res
= dns_conn
.DnssrvOperation2(client_version
, 0, server
, None,
875 0, 'ZoneCreate', typeid
,
877 self
.outf
.write('Zone %s created successfully\n' % zone
)
880 class cmd_zonedelete(Command
):
883 synopsis
= '%prog <server> <zone> [options]'
885 takes_args
= [ 'server', 'zone' ]
887 takes_optiongroups
= {
888 "sambaopts": options
.SambaOptions
,
889 "versionopts": options
.VersionOptions
,
890 "credopts": options
.CredentialsOptions
,
893 def run(self
, server
, zone
, sambaopts
=None, credopts
=None,
896 self
.lp
= sambaopts
.get_loadparm()
897 self
.creds
= credopts
.get_credentials(self
.lp
)
898 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
901 res
= dns_conn
.DnssrvOperation2(dnsserver
.DNS_CLIENT_VERSION_LONGHORN
,
902 0, server
, zone
, 0, 'DeleteZoneFromDs',
903 dnsserver
.DNSSRV_TYPEID_NULL
,
905 self
.outf
.write('Zone %s delete successfully\n' % zone
)
908 class cmd_query(Command
):
911 synopsis
= '%prog <server> <zone> <name> <A|AAAA|CNAME|MX|NS|SOA|SRV|TXT|ALL> [options]'
913 takes_args
= [ 'server', 'zone', 'name', 'rtype' ]
915 takes_optiongroups
= {
916 "sambaopts": options
.SambaOptions
,
917 "versionopts": options
.VersionOptions
,
918 "credopts": options
.CredentialsOptions
,
922 Option('--authority', help='Search authoritative records (default)',
923 action
='store_true', dest
='authority'),
924 Option('--cache', help='Search cached records',
925 action
='store_true', dest
='cache'),
926 Option('--glue', help='Search glue records',
927 action
='store_true', dest
='glue'),
928 Option('--root', help='Search root hints',
929 action
='store_true', dest
='root'),
930 Option('--additional', help='List additional records',
931 action
='store_true', dest
='additional'),
932 Option('--no-children', help='Do not list children',
933 action
='store_true', dest
='no_children'),
934 Option('--only-children', help='List only children',
935 action
='store_true', dest
='only_children')
938 def run(self
, server
, zone
, name
, rtype
, authority
=False, cache
=False,
939 glue
=False, root
=False, additional
=False, no_children
=False,
940 only_children
=False, sambaopts
=None, credopts
=None,
942 record_type
= dns_type_flag(rtype
)
946 select_flags |
= dnsserver
.DNS_RPC_VIEW_AUTHORITY_DATA
948 select_flags |
= dnsserver
.DNS_RPC_VIEW_CACHE_DATA
950 select_flags |
= dnsserver
.DNS_RPC_VIEW_GLUE_DATA
952 select_flags |
= dnsserver
.DNS_RPC_VIEW_ROOT_HINT_DATA
954 select_flags |
= dnsserver
.DNS_RPC_VIEW_ADDITIONAL_DATA
956 select_flags |
= dnsserver
.DNS_RPC_VIEW_NO_CHILDREN
958 select_flags |
= dnsserver
.DNS_RPC_VIEW_ONLY_CHILDREN
960 if select_flags
== 0:
961 select_flags
= dnsserver
.DNS_RPC_VIEW_AUTHORITY_DATA
963 if select_flags
== dnsserver
.DNS_RPC_VIEW_ADDITIONAL_DATA
:
964 self
.outf
.write('Specify either --authority or --root along with --additional.\n')
965 self
.outf
.write('Assuming --authority.\n')
966 select_flags |
= dnsserver
.DNS_RPC_VIEW_AUTHORITY_DATA
968 self
.lp
= sambaopts
.get_loadparm()
969 self
.creds
= credopts
.get_credentials(self
.lp
)
970 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
972 buflen
, res
= dns_conn
.DnssrvEnumRecords2(
973 dnsserver
.DNS_CLIENT_VERSION_LONGHORN
, 0, server
, zone
, name
,
974 None, record_type
, select_flags
, None, None)
975 print_dnsrecords(self
.outf
, res
)
978 class cmd_roothints(Command
):
979 """Query root hints."""
981 synopsis
= '%prog <server> [<name>] [options]'
983 takes_args
= [ 'server', 'name?' ]
985 takes_optiongroups
= {
986 "sambaopts": options
.SambaOptions
,
987 "versionopts": options
.VersionOptions
,
988 "credopts": options
.CredentialsOptions
,
991 def run(self
, server
, name
='.', sambaopts
=None, credopts
=None,
993 record_type
= dnsp
.DNS_TYPE_NS
994 select_flags
= (dnsserver
.DNS_RPC_VIEW_ROOT_HINT_DATA |
995 dnsserver
.DNS_RPC_VIEW_ADDITIONAL_DATA
)
997 self
.lp
= sambaopts
.get_loadparm()
998 self
.creds
= credopts
.get_credentials(self
.lp
)
999 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
1001 buflen
, res
= dns_conn
.DnssrvEnumRecords2(
1002 dnsserver
.DNS_CLIENT_VERSION_LONGHORN
, 0, server
, '..RootHints',
1003 name
, None, record_type
, select_flags
, None, None)
1004 print_dnsrecords(self
.outf
, res
)
1007 class cmd_add_record(Command
):
1010 For each type data contents are as follows:
1011 A ipv4_address_string
1012 AAAA ipv6_address_string
1016 MX "fqdn_string preference"
1017 SRV "fqdn_string port priority weight"
1018 TXT "'string1' 'string2' ..."
1021 synopsis
= '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SRV|TXT> <data>'
1023 takes_args
= [ 'server', 'zone', 'name', 'rtype', 'data' ]
1025 takes_optiongroups
= {
1026 "sambaopts": options
.SambaOptions
,
1027 "versionopts": options
.VersionOptions
,
1028 "credopts": options
.CredentialsOptions
,
1031 def run(self
, server
, zone
, name
, rtype
, data
, sambaopts
=None,
1032 credopts
=None, versionopts
=None):
1034 if rtype
.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SRV','TXT'):
1035 raise CommandError('Adding record of type %s is not supported' % rtype
)
1037 record_type
= dns_type_flag(rtype
)
1038 rec
= data_to_dns_record(record_type
, data
)
1040 self
.lp
= sambaopts
.get_loadparm()
1041 self
.creds
= credopts
.get_credentials(self
.lp
)
1042 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
1044 rec_match
= dns_record_match(dns_conn
, server
, zone
, name
, record_type
,
1046 if rec_match
is not None:
1047 raise CommandError('Record already exists')
1049 add_rec_buf
= dnsserver
.DNS_RPC_RECORD_BUF()
1050 add_rec_buf
.rec
= rec
1052 dns_conn
.DnssrvUpdateRecord2(dnsserver
.DNS_CLIENT_VERSION_LONGHORN
,
1053 0, server
, zone
, name
, add_rec_buf
, None)
1054 self
.outf
.write('Record added successfully\n')
1057 class cmd_update_record(Command
):
1058 """Update a DNS record
1060 For each type data contents are as follows:
1061 A ipv4_address_string
1062 AAAA ipv6_address_string
1066 MX "fqdn_string preference"
1067 SRV "fqdn_string port priority weight"
1068 TXT "'string1' 'string2' ..."
1071 synopsis
= '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SRV|TXT> <olddata> <newdata>'
1073 takes_args
= [ 'server', 'zone', 'name', 'rtype', 'olddata', 'newdata' ]
1075 takes_optiongroups
= {
1076 "sambaopts": options
.SambaOptions
,
1077 "versionopts": options
.VersionOptions
,
1078 "credopts": options
.CredentialsOptions
,
1081 def run(self
, server
, zone
, name
, rtype
, olddata
, newdata
,
1082 sambaopts
=None, credopts
=None, versionopts
=None):
1084 if rtype
.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SRV','TXT'):
1085 raise CommandError('Updating record of type %s is not supported' % rtype
)
1087 record_type
= dns_type_flag(rtype
)
1088 rec
= data_to_dns_record(record_type
, newdata
)
1090 self
.lp
= sambaopts
.get_loadparm()
1091 self
.creds
= credopts
.get_credentials(self
.lp
)
1092 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
1094 rec_match
= dns_record_match(dns_conn
, server
, zone
, name
, record_type
,
1097 raise CommandError('Record does not exist')
1099 # Copy properties from existing record to new record
1100 rec
.dwFlags
= rec_match
.dwFlags
1101 rec
.dwSerial
= rec_match
.dwSerial
1102 rec
.dwTtlSeconds
= rec_match
.dwTtlSeconds
1103 rec
.dwTimeStamp
= rec_match
.dwTimeStamp
1105 add_rec_buf
= dnsserver
.DNS_RPC_RECORD_BUF()
1106 add_rec_buf
.rec
= rec
1108 del_rec_buf
= dnsserver
.DNS_RPC_RECORD_BUF()
1109 del_rec_buf
.rec
= rec_match
1111 dns_conn
.DnssrvUpdateRecord2(dnsserver
.DNS_CLIENT_VERSION_LONGHORN
,
1118 self
.outf
.write('Record updated succefully\n')
1121 class cmd_delete_record(Command
):
1122 """Delete a DNS record
1124 For each type data contents are as follows:
1125 A ipv4_address_string
1126 AAAA ipv6_address_string
1130 MX "fqdn_string preference"
1131 SRV "fqdn_string port priority weight"
1132 TXT "'string1' 'string2' ..."
1135 synopsis
= '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SRV|TXT> <data>'
1137 takes_args
= [ 'server', 'zone', 'name', 'rtype', 'data' ]
1139 takes_optiongroups
= {
1140 "sambaopts": options
.SambaOptions
,
1141 "versionopts": options
.VersionOptions
,
1142 "credopts": options
.CredentialsOptions
,
1145 def run(self
, server
, zone
, name
, rtype
, data
, sambaopts
=None, credopts
=None, versionopts
=None):
1147 if rtype
.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SRV','TXT'):
1148 raise CommandError('Deleting record of type %s is not supported' % rtype
)
1150 record_type
= dns_type_flag(rtype
)
1152 self
.lp
= sambaopts
.get_loadparm()
1153 self
.creds
= credopts
.get_credentials(self
.lp
)
1154 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
1156 rec_match
= dns_record_match(dns_conn
, server
, zone
, name
, record_type
, data
)
1158 raise CommandError('Record does not exist')
1160 del_rec_buf
= dnsserver
.DNS_RPC_RECORD_BUF()
1161 del_rec_buf
.rec
= rec_match
1163 dns_conn
.DnssrvUpdateRecord2(dnsserver
.DNS_CLIENT_VERSION_LONGHORN
,
1170 self
.outf
.write('Record deleted succefully\n')
1173 class cmd_dns(SuperCommand
):
1174 """Domain Name Service (DNS) management."""
1177 subcommands
['serverinfo'] = cmd_serverinfo()
1178 subcommands
['zoneinfo'] = cmd_zoneinfo()
1179 subcommands
['zonelist'] = cmd_zonelist()
1180 subcommands
['zonecreate'] = cmd_zonecreate()
1181 subcommands
['zonedelete'] = cmd_zonedelete()
1182 subcommands
['query'] = cmd_query()
1183 subcommands
['roothints'] = cmd_roothints()
1184 subcommands
['add'] = cmd_add_record()
1185 subcommands
['update'] = cmd_update_record()
1186 subcommands
['delete'] = cmd_delete_record()