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
22 from socket
import inet_ntop
23 from socket
import AF_INET
24 from socket
import AF_INET6
27 from samba
.netcmd
import (
33 from samba
.dcerpc
import dnsp
, dnsserver
36 def dns_connect(server
, lp
, creds
):
37 if server
.lower() == 'localhost':
39 binding_str
= "ncacn_ip_tcp:%s[sign]" % server
40 dns_conn
= dnsserver
.dnsserver(binding_str
, lp
, creds
)
44 def bool_string(flag
):
50 ret
= 'UNKNOWN (0x%x)' % flag
54 def enum_string(module
, enum_defs
, value
):
57 if value
== getattr(module
, e
):
61 ret
= 'UNKNOWN (0x%x)' % value
65 def bitmap_string(module
, bitmap_defs
, value
):
68 if value
& getattr(module
, b
):
75 def boot_method_string(boot_method
):
76 enum_defs
= [ 'DNS_BOOT_METHOD_UNINITIALIZED', 'DNS_BOOT_METHOD_FILE',
77 'DNS_BOOT_METHOD_REGISTRY', 'DNS_BOOT_METHOD_DIRECTORY' ]
78 return enum_string(dnsserver
, enum_defs
, boot_method
)
81 def name_check_flag_string(check_flag
):
82 enum_defs
= [ 'DNS_ALLOW_RFC_NAMES_ONLY', 'DNS_ALLOW_NONRFC_NAMES',
83 'DNS_ALLOW_MULTIBYTE_NAMES', 'DNS_ALLOW_ALL_NAMES' ]
84 return enum_string(dnsserver
, enum_defs
, check_flag
)
87 def zone_type_string(zone_type
):
88 enum_defs
= [ 'DNS_ZONE_TYPE_CACHE', 'DNS_ZONE_TYPE_PRIMARY',
89 'DNS_ZONE_TYPE_SECONDARY', 'DNS_ZONE_TYPE_STUB',
90 'DNS_ZONE_TYPE_FORWARDER', 'DNS_ZONE_TYPE_SECONDARY_CACHE' ]
91 return enum_string(dnsp
, enum_defs
, zone_type
)
94 def zone_update_string(zone_update
):
95 enum_defs
= [ 'DNS_ZONE_UPDATE_OFF', 'DNS_ZONE_UPDATE_UNSECURE',
96 'DNS_ZONE_UPDATE_SECURE' ]
97 return enum_string(dnsp
, enum_defs
, zone_update
)
100 def zone_secondary_security_string(security
):
101 enum_defs
= [ 'DNS_ZONE_SECSECURE_NO_SECURITY', 'DNS_ZONE_SECSECURE_NS_ONLY',
102 'DNS_ZONE_SECSECURE_LIST_ONLY', 'DNS_ZONE_SECSECURE_NO_XFER' ]
103 return enum_string(dnsserver
, enum_defs
, security
)
106 def zone_notify_level_string(notify_level
):
107 enum_defs
= [ 'DNS_ZONE_NOTIFY_OFF', 'DNS_ZONE_NOTIFY_ALL_SECONDARIES',
108 'DNS_ZONE_NOTIFY_LIST_ONLY' ]
109 return enum_string(dnsserver
, enum_defs
, notify_level
)
112 def dp_flags_string(dp_flags
):
113 bitmap_defs
= [ 'DNS_DP_AUTOCREATED', 'DNS_DP_LEGACY', 'DNS_DP_DOMAIN_DEFAULT',
114 'DNS_DP_FOREST_DEFAULT', 'DNS_DP_ENLISTED', 'DNS_DP_DELETED' ]
115 return bitmap_string(dnsserver
, bitmap_defs
, dp_flags
)
118 def zone_flags_string(flags
):
119 bitmap_defs
= [ 'DNS_RPC_ZONE_PAUSED', 'DNS_RPC_ZONE_SHUTDOWN',
120 'DNS_RPC_ZONE_REVERSE', 'DNS_RPC_ZONE_AUTOCREATED',
121 'DNS_RPC_ZONE_DSINTEGRATED', 'DNS_RPC_ZONE_AGING',
122 'DNS_RPC_ZONE_UPDATE_UNSECURE', 'DNS_RPC_ZONE_UPDATE_SECURE',
123 'DNS_RPC_ZONE_READONLY']
124 return bitmap_string(dnsserver
, bitmap_defs
, flags
)
127 def ip4_array_string(array
):
131 for i
in xrange(array
.AddrCount
):
132 addr
= inet_ntop(AF_INET
, pack('I', array
.AddrArray
[i
]))
137 def dns_addr_array_string(array
):
141 for i
in xrange(array
.AddrCount
):
142 if array
.AddrArray
[i
].MaxSa
[0] == 0x02:
143 x
= "".join([chr(b
) for b
in array
.AddrArray
[i
].MaxSa
])[4:8]
144 addr
= inet_ntop(AF_INET
, x
)
145 elif array
.AddrArray
[i
].MaxSa
[0] == 0x17:
146 x
= "".join([chr(b
) for b
in array
.AddrArray
[i
].MaxSa
])[8:24]
147 addr
= inet_ntop(AF_INET6
, x
)
154 def dns_type_flag(rec_type
):
155 rtype
= rec_type
.upper()
157 record_type
= dnsp
.DNS_TYPE_A
158 elif rtype
== 'AAAA':
159 record_type
= dnsp
.DNS_TYPE_AAAA
161 record_type
= dnsp
.DNS_TYPE_PTR
163 record_type
= dnsp
.DNS_TYPE_NS
164 elif rtype
== 'CNAME':
165 record_type
= dnsp
.DNS_TYPE_CNAME
167 record_type
= dnsp
.DNS_TYPE_SOA
169 record_type
= dnsp
.DNS_TYPE_MX
171 record_type
= dnsp
.DNS_TYPE_SRV
173 record_type
= dnsp
.DNS_TYPE_TXT
175 record_type
= dnsp
.DNS_TYPE_ALL
177 raise CommandError('Unknown type of DNS record %s' % rec_type
)
181 def dns_client_version(cli_version
):
182 version
= cli_version
.upper()
184 client_version
= dnsserver
.DNS_CLIENT_VERSION_W2K
185 elif version
== 'DOTNET':
186 client_version
= dnsserver
.DNS_CLIENT_VERSION_DOTNET
187 elif version
== 'LONGHORN':
188 client_version
= dnsserver
.DNS_CLIENT_VERSION_LONGHORN
190 raise CommandError('Unknown client version %s' % cli_version
)
191 return client_version
194 def print_serverinfo(outf
, typeid
, serverinfo
):
195 outf
.write(' dwVersion : 0x%x\n' % serverinfo
.dwVersion
)
196 outf
.write(' fBootMethod : %s\n' % boot_method_string(serverinfo
.fBootMethod
))
197 outf
.write(' fAdminConfigured : %s\n' % bool_string(serverinfo
.fAdminConfigured
))
198 outf
.write(' fAllowUpdate : %s\n' % bool_string(serverinfo
.fAllowUpdate
))
199 outf
.write(' fDsAvailable : %s\n' % bool_string(serverinfo
.fDsAvailable
))
200 outf
.write(' pszServerName : %s\n' % serverinfo
.pszServerName
)
201 outf
.write(' pszDsContainer : %s\n' % serverinfo
.pszDsContainer
)
203 if typeid
!= dnsserver
.DNSSRV_TYPEID_SERVER_INFO
:
204 outf
.write(' aipServerAddrs : %s\n' %
205 ip4_array_string(serverinfo
.aipServerAddrs
))
206 outf
.write(' aipListenAddrs : %s\n' %
207 ip4_array_string(serverinfo
.aipListenAddrs
))
208 outf
.write(' aipForwarders : %s\n' %
209 ip4_array_string(serverinfo
.aipForwarders
))
211 outf
.write(' aipServerAddrs : %s\n' %
212 dns_addr_array_string(serverinfo
.aipServerAddrs
))
213 outf
.write(' aipListenAddrs : %s\n' %
214 dns_addr_array_string(serverinfo
.aipListenAddrs
))
215 outf
.write(' aipForwarders : %s\n' %
216 dns_addr_array_string(serverinfo
.aipForwarders
))
218 outf
.write(' dwLogLevel : %d\n' % serverinfo
.dwLogLevel
)
219 outf
.write(' dwDebugLevel : %d\n' % serverinfo
.dwDebugLevel
)
220 outf
.write(' dwForwardTimeout : %d\n' % serverinfo
.dwForwardTimeout
)
221 outf
.write(' dwRpcPrototol : 0x%x\n' % serverinfo
.dwRpcProtocol
)
222 outf
.write(' dwNameCheckFlag : %s\n' % name_check_flag_string(serverinfo
.dwNameCheckFlag
))
223 outf
.write(' cAddressAnswerLimit : %d\n' % serverinfo
.cAddressAnswerLimit
)
224 outf
.write(' dwRecursionRetry : %d\n' % serverinfo
.dwRecursionRetry
)
225 outf
.write(' dwRecursionTimeout : %d\n' % serverinfo
.dwRecursionTimeout
)
226 outf
.write(' dwMaxCacheTtl : %d\n' % serverinfo
.dwMaxCacheTtl
)
227 outf
.write(' dwDsPollingInterval : %d\n' % serverinfo
.dwDsPollingInterval
)
228 outf
.write(' dwScavengingInterval : %d\n' % serverinfo
.dwScavengingInterval
)
229 outf
.write(' dwDefaultRefreshInterval : %d\n' % serverinfo
.dwDefaultRefreshInterval
)
230 outf
.write(' dwDefaultNoRefreshInterval : %d\n' % serverinfo
.dwDefaultNoRefreshInterval
)
231 outf
.write(' fAutoReverseZones : %s\n' % bool_string(serverinfo
.fAutoReverseZones
))
232 outf
.write(' fAutoCacheUpdate : %s\n' % bool_string(serverinfo
.fAutoCacheUpdate
))
233 outf
.write(' fRecurseAfterForwarding : %s\n' % bool_string(serverinfo
.fRecurseAfterForwarding
))
234 outf
.write(' fForwardDelegations : %s\n' % bool_string(serverinfo
.fForwardDelegations
))
235 outf
.write(' fNoRecursion : %s\n' % bool_string(serverinfo
.fNoRecursion
))
236 outf
.write(' fSecureResponses : %s\n' % bool_string(serverinfo
.fSecureResponses
))
237 outf
.write(' fRoundRobin : %s\n' % bool_string(serverinfo
.fRoundRobin
))
238 outf
.write(' fLocalNetPriority : %s\n' % bool_string(serverinfo
.fLocalNetPriority
))
239 outf
.write(' fBindSecondaries : %s\n' % bool_string(serverinfo
.fBindSecondaries
))
240 outf
.write(' fWriteAuthorityNs : %s\n' % bool_string(serverinfo
.fWriteAuthorityNs
))
241 outf
.write(' fStrictFileParsing : %s\n' % bool_string(serverinfo
.fStrictFileParsing
))
242 outf
.write(' fLooseWildcarding : %s\n' % bool_string(serverinfo
.fLooseWildcarding
))
243 outf
.write(' fDefaultAgingState : %s\n' % bool_string(serverinfo
.fDefaultAgingState
))
245 if typeid
!= dnsserver
.DNSSRV_TYPEID_SERVER_INFO_W2K
:
246 outf
.write(' dwRpcStructureVersion : 0x%x\n' % serverinfo
.dwRpcStructureVersion
)
247 outf
.write(' aipLogFilter : %s\n' % dns_addr_array_string(serverinfo
.aipLogFilter
))
248 outf
.write(' pwszLogFilePath : %s\n' % serverinfo
.pwszLogFilePath
)
249 outf
.write(' pszDomainName : %s\n' % serverinfo
.pszDomainName
)
250 outf
.write(' pszForestName : %s\n' % serverinfo
.pszForestName
)
251 outf
.write(' pszDomainDirectoryPartition : %s\n' % serverinfo
.pszDomainDirectoryPartition
)
252 outf
.write(' pszForestDirectoryPartition : %s\n' % serverinfo
.pszForestDirectoryPartition
)
254 outf
.write(' dwLocalNetPriorityNetMask : 0x%x\n' % serverinfo
.dwLocalNetPriorityNetMask
)
255 outf
.write(' dwLastScavengeTime : %d\n' % serverinfo
.dwLastScavengeTime
)
256 outf
.write(' dwEventLogLevel : %d\n' % serverinfo
.dwEventLogLevel
)
257 outf
.write(' dwLogFileMaxSize : %d\n' % serverinfo
.dwLogFileMaxSize
)
258 outf
.write(' dwDsForestVersion : %d\n' % serverinfo
.dwDsForestVersion
)
259 outf
.write(' dwDsDomainVersion : %d\n' % serverinfo
.dwDsDomainVersion
)
260 outf
.write(' dwDsDsaVersion : %d\n' % serverinfo
.dwDsDsaVersion
)
262 if typeid
== dnsserver
.DNSSRV_TYPEID_SERVER_INFO
:
263 outf
.write(' fReadOnlyDC : %s\n' % bool_string(serverinfo
.fReadOnlyDC
))
266 def print_zoneinfo(outf
, typeid
, zoneinfo
):
267 outf
.write(' pszZoneName : %s\n' % zoneinfo
.pszZoneName
)
268 outf
.write(' dwZoneType : %s\n' % zone_type_string(zoneinfo
.dwZoneType
))
269 outf
.write(' fReverse : %s\n' % bool_string(zoneinfo
.fReverse
))
270 outf
.write(' fAllowUpdate : %s\n' % zone_update_string(zoneinfo
.fAllowUpdate
))
271 outf
.write(' fPaused : %s\n' % bool_string(zoneinfo
.fPaused
))
272 outf
.write(' fShutdown : %s\n' % bool_string(zoneinfo
.fShutdown
))
273 outf
.write(' fAutoCreated : %s\n' % bool_string(zoneinfo
.fAutoCreated
))
274 outf
.write(' fUseDatabase : %s\n' % bool_string(zoneinfo
.fUseDatabase
))
275 outf
.write(' pszDataFile : %s\n' % zoneinfo
.pszDataFile
)
276 if typeid
!= dnsserver
.DNSSRV_TYPEID_ZONE_INFO
:
277 outf
.write(' aipMasters : %s\n' %
278 ip4_array_string(zoneinfo
.aipMasters
))
280 outf
.write(' aipMasters : %s\n' %
281 dns_addr_array_string(zoneinfo
.aipMasters
))
282 outf
.write(' fSecureSecondaries : %s\n' % zone_secondary_security_string(zoneinfo
.fSecureSecondaries
))
283 outf
.write(' fNotifyLevel : %s\n' % zone_notify_level_string(zoneinfo
.fNotifyLevel
))
284 if typeid
!= dnsserver
.DNSSRV_TYPEID_ZONE_INFO
:
285 outf
.write(' aipSecondaries : %s\n' %
286 ip4_array_string(zoneinfo
.aipSecondaries
))
287 outf
.write(' aipNotify : %s\n' %
288 ip4_array_string(zoneinfo
.aipNotify
))
290 outf
.write(' aipSecondaries : %s\n' %
291 dns_addr_array_string(zoneinfo
.aipSecondaries
))
292 outf
.write(' aipNotify : %s\n' %
293 dns_addr_array_string(zoneinfo
.aipNotify
))
294 outf
.write(' fUseWins : %s\n' % bool_string(zoneinfo
.fUseWins
))
295 outf
.write(' fUseNbstat : %s\n' % bool_string(zoneinfo
.fUseNbstat
))
296 outf
.write(' fAging : %s\n' % bool_string(zoneinfo
.fAging
))
297 outf
.write(' dwNoRefreshInterval : %d\n' % zoneinfo
.dwNoRefreshInterval
)
298 outf
.write(' dwRefreshInterval : %d\n' % zoneinfo
.dwRefreshInterval
)
299 outf
.write(' dwAvailForScavengeTime : %d\n' % zoneinfo
.dwAvailForScavengeTime
)
300 if typeid
!= dnsserver
.DNSSRV_TYPEID_ZONE_INFO
:
301 outf
.write(' aipScavengeServers : %s\n' %
302 ip4_array_string(zoneinfo
.aipScavengeServers
))
304 outf
.write(' aipScavengeServers : %s\n' %
305 dns_addr_array_string(zoneinfo
.aipScavengeServers
))
307 if typeid
!= dnsserver
.DNSSRV_TYPEID_ZONE_INFO_W2K
:
308 outf
.write(' dwRpcStructureVersion : 0x%x\n' % zoneinfo
.dwRpcStructureVersion
)
309 outf
.write(' dwForwarderTimeout : %d\n' % zoneinfo
.dwForwarderTimeout
)
310 outf
.write(' fForwarderSlave : %d\n' % zoneinfo
.fForwarderSlave
)
311 if typeid
!= dnsserver
.DNSSRV_TYPEID_ZONE_INFO
:
312 outf
.write(' aipLocalMasters : %s\n' %
313 ip4_array_string(zoneinfo
.aipLocalMasters
))
315 outf
.write(' aipLocalMasters : %s\n' %
316 dns_addr_array_string(zoneinfo
.aipLocalMasters
))
317 outf
.write(' dwDpFlags : %s\n' % dp_flags_string(zoneinfo
.dwDpFlags
))
318 outf
.write(' pszDpFqdn : %s\n' % zoneinfo
.pszDpFqdn
)
319 outf
.write(' pwszZoneDn : %s\n' % zoneinfo
.pwszZoneDn
)
320 outf
.write(' dwLastSuccessfulSoaCheck : %d\n' % zoneinfo
.dwLastSuccessfulSoaCheck
)
321 outf
.write(' dwLastSuccessfulXfr : %d\n' % zoneinfo
.dwLastSuccessfulXfr
)
323 if typeid
== dnsserver
.DNSSRV_TYPEID_ZONE_INFO
:
324 outf
.write(' fQueuedForBackgroundLoad : %s\n' % bool_string(zoneinfo
.fQueuedForBackgroundLoad
))
325 outf
.write(' fBackgroundLoadInProgress : %s\n' % bool_string(zoneinfo
.fBackgroundLoadInProgress
))
326 outf
.write(' fReadOnlyZone : %s\n' % bool_string(zoneinfo
.fReadOnlyZone
))
327 outf
.write(' dwLastXfrAttempt : %d\n' % zoneinfo
.dwLastXfrAttempt
)
328 outf
.write(' dwLastXfrResult : %d\n' % zoneinfo
.dwLastXfrResult
)
331 def print_zone(outf
, typeid
, zone
):
332 outf
.write(' pszZoneName : %s\n' % zone
.pszZoneName
)
333 outf
.write(' Flags : %s\n' % zone_flags_string(zone
.Flags
))
334 outf
.write(' ZoneType : %s\n' % zone_type_string(zone
.ZoneType
))
335 outf
.write(' Version : %s\n' % zone
.Version
)
337 if typeid
!= dnsserver
.DNSSRV_TYPEID_ZONE_W2K
:
338 outf
.write(' dwDpFlags : %s\n' % dp_flags_string(zone
.dwDpFlags
))
339 outf
.write(' pszDpFqdn : %s\n' % zone
.pszDpFqdn
)
342 def print_enumzones(outf
, typeid
, zones
):
343 outf
.write(' %d zone(s) found\n' % zones
.dwZoneCount
)
344 for zone
in zones
.ZoneArray
:
346 print_zone(outf
, typeid
, zone
)
349 def print_dns_record(outf
, rec
):
350 if rec
.wType
== dnsp
.DNS_TYPE_A
:
351 mesg
= 'A: %s' % (rec
.data
)
352 elif rec
.wType
== dnsp
.DNS_TYPE_AAAA
:
353 mesg
= 'AAAA: %s' % (rec
.data
)
354 elif rec
.wType
== dnsp
.DNS_TYPE_PTR
:
355 mesg
= 'PTR: %s' % (rec
.data
.str)
356 elif rec
.wType
== dnsp
.DNS_TYPE_NS
:
357 mesg
= 'NS: %s' % (rec
.data
.str)
358 elif rec
.wType
== dnsp
.DNS_TYPE_CNAME
:
359 mesg
= 'CNAME: %s' % (rec
.data
.str)
360 elif rec
.wType
== dnsp
.DNS_TYPE_SOA
:
361 mesg
= 'SOA: serial=%d, refresh=%d, retry=%d, expire=%d, minttl=%d, ns=%s, email=%s' % (
366 rec
.data
.dwMinimumTtl
,
367 rec
.data
.NamePrimaryServer
.str,
368 rec
.data
.ZoneAdministratorEmail
.str)
369 elif rec
.wType
== dnsp
.DNS_TYPE_MX
:
370 mesg
= 'MX: %s (%d)' % (rec
.data
.nameExchange
.str, rec
.data
.wPreference
)
371 elif rec
.wType
== dnsp
.DNS_TYPE_SRV
:
372 mesg
= 'SRV: %s (%d, %d, %d)' % (rec
.data
.nameTarget
.str, rec
.data
.wPort
,
373 rec
.data
.wPriority
, rec
.data
.wWeight
)
374 elif rec
.wType
== dnsp
.DNS_TYPE_TXT
:
375 slist
= ['"%s"' % name
.str for name
in rec
.data
.str]
376 mesg
= 'TXT: %s' % ','.join(slist
)
379 outf
.write(' %s (flags=%x, serial=%d, ttl=%d)\n' % (
380 mesg
, rec
.dwFlags
, rec
.dwSerial
, rec
.dwTtlSeconds
))
383 def print_dnsrecords(outf
, records
):
384 for rec
in records
.rec
:
385 outf
.write(' Name=%s, Records=%d, Children=%d\n' % (
389 for dns_rec
in rec
.records
:
390 print_dns_record(outf
, dns_rec
)
394 # Always create a copy of strings when creating DNS_RPC_RECORDs
395 # to overcome the bug in pidl generated python bindings.
398 class ARecord(dnsserver
.DNS_RPC_RECORD
):
399 def __init__(self
, ip_addr
, serial
=1, ttl
=900, rank
=dnsp
.DNS_RANK_ZONE
,
401 super(ARecord
, self
).__init
__()
402 self
.wType
= dnsp
.DNS_TYPE_A
403 self
.dwFlags
= rank | node_flag
404 self
.dwSerial
= serial
405 self
.dwTtlSeconds
= ttl
406 self
._ip
_addr
= ip_addr
[:]
407 self
.data
= self
._ip
_addr
410 class AAAARecord(dnsserver
.DNS_RPC_RECORD
):
412 def __init__(self
, ip6_addr
, serial
=1, ttl
=900, rank
=dnsp
.DNS_RANK_ZONE
,
414 super(AAAARecord
, self
).__init
__()
415 self
.wType
= dnsp
.DNS_TYPE_AAAA
416 self
.dwFlags
= rank | node_flag
417 self
.dwSerial
= serial
418 self
.dwTtlSeconds
= ttl
419 self
._ip
6_addr
= ip6_addr
[:]
420 self
.data
= self
._ip
6_addr
423 class PTRRecord(dnsserver
.DNS_RPC_RECORD
):
425 def __init__(self
, ptr
, serial
=1, ttl
=900, rank
=dnsp
.DNS_RANK_ZONE
,
427 super(PTRRecord
, self
).__init
__()
428 self
.wType
= dnsp
.DNS_TYPE_PTR
429 self
.dwFlags
= rank | node_flag
430 self
.dwSerial
= serial
431 self
.dwTtlSeconds
= ttl
433 ptr_name
= dnsserver
.DNS_RPC_NAME()
434 ptr_name
.str = self
._ptr
435 ptr_name
.len = len(ptr
)
439 class CNameRecord(dnsserver
.DNS_RPC_RECORD
):
441 def __init__(self
, cname
, serial
=1, ttl
=900, rank
=dnsp
.DNS_RANK_ZONE
,
443 super(CNameRecord
, self
).__init
__()
444 self
.wType
= dnsp
.DNS_TYPE_CNAME
445 self
.dwFlags
= rank | node_flag
446 self
.dwSerial
= serial
447 self
.dwTtlSeconds
= ttl
448 self
._cname
= cname
[:]
449 cname_name
= dnsserver
.DNS_RPC_NAME()
450 cname_name
.str = self
._cname
451 cname_name
.len = len(cname
)
452 self
.data
= cname_name
455 class NSRecord(dnsserver
.DNS_RPC_RECORD
):
457 def __init__(self
, dns_server
, serial
=1, ttl
=900, rank
=dnsp
.DNS_RANK_ZONE
,
459 super(NSRecord
, self
).__init
__()
460 self
.wType
= dnsp
.DNS_TYPE_NS
461 self
.dwFlags
= rank | node_flag
462 self
.dwSerial
= serial
463 self
.dwTtlSeconds
= ttl
464 self
._dns
_server
= dns_server
[:]
465 ns
= dnsserver
.DNS_RPC_NAME()
466 ns
.str = self
._dns
_server
467 ns
.len = len(dns_server
)
471 class MXRecord(dnsserver
.DNS_RPC_RECORD
):
473 def __init__(self
, mail_server
, preference
, serial
=1, ttl
=900,
474 rank
=dnsp
.DNS_RANK_ZONE
, node_flag
=0):
475 super(MXRecord
, self
).__init
__()
476 self
.wType
= dnsp
.DNS_TYPE_MX
477 self
.dwFlags
= rank | node_flag
478 self
.dwSerial
= serial
479 self
.dwTtlSeconds
= ttl
480 self
._mail
_server
= mail_server
[:]
481 mx
= dnsserver
.DNS_RPC_RECORD_NAME_PREFERENCE()
482 mx
.wPreference
= preference
483 mx
.nameExchange
.str = self
._mail
_server
484 mx
.nameExchange
.len = len(mail_server
)
488 class SOARecord(dnsserver
.DNS_RPC_RECORD
):
490 def __init__(self
, mname
, rname
, serial
=1, refresh
=900, retry
=600,
491 expire
=86400, minimum
=3600, ttl
=3600, rank
=dnsp
.DNS_RANK_ZONE
,
492 node_flag
=dnsp
.DNS_RPC_FLAG_AUTH_ZONE_ROOT
):
493 super(SOARecord
, self
).__init
__()
494 self
.wType
= dnsp
.DNS_TYPE_SOA
495 self
.dwFlags
= rank | node_flag
496 self
.dwSerial
= serial
497 self
.dwTtlSeconds
= ttl
498 self
._mname
= mname
[:]
499 self
._rname
= rname
[:]
500 soa
= dnsserver
.DNS_RPC_RECORD_SOA()
501 soa
.dwSerialNo
= serial
502 soa
.dwRefresh
= refresh
504 soa
.dwExpire
= expire
505 soa
.dwMinimumTtl
= minimum
506 soa
.NamePrimaryServer
.str = self
._mname
507 soa
.NamePrimaryServer
.len = len(mname
)
508 soa
.ZoneAdministratorEmail
.str = self
._rname
509 soa
.ZoneAdministratorEmail
.len = len(rname
)
513 class SRVRecord(dnsserver
.DNS_RPC_RECORD
):
515 def __init__(self
, target
, port
, priority
=0, weight
=100, serial
=1, ttl
=900,
516 rank
=dnsp
.DNS_RANK_ZONE
, node_flag
=0):
517 super(SRVRecord
, self
).__init
__()
518 self
.wType
= dnsp
.DNS_TYPE_SRV
519 self
.dwFlags
= rank | node_flag
520 self
.dwSerial
= serial
521 self
.dwTtlSeconds
= ttl
522 self
._target
= target
[:]
523 srv
= dnsserver
.DNS_RPC_RECORD_SRV()
524 srv
.wPriority
= priority
527 srv
.nameTarget
.str = self
._target
528 srv
.nameTarget
.len = len(target
)
532 class TXTRecord(dnsserver
.DNS_RPC_RECORD
):
534 def __init__(self
, slist
, serial
=1, ttl
=900, rank
=dnsp
.DNS_RANK_ZONE
,
536 super(TXTRecord
, self
).__init
__()
537 self
.wType
= dnsp
.DNS_TYPE_TXT
538 self
.dwFlags
= rank | node_flag
539 self
.dwSerial
= serial
540 self
.dwTtlSeconds
= ttl
543 self
._slist
.append(s
[:])
545 for s
in self
._slist
:
546 name
= dnsserver
.DNS_RPC_NAME()
550 txt
= dnsserver
.DNS_RPC_RECORD_STRING()
551 txt
.count
= len(slist
)
556 # Convert data into a dns record
557 def data_to_dns_record(record_type
, data
):
558 if record_type
== dnsp
.DNS_TYPE_A
:
560 elif record_type
== dnsp
.DNS_TYPE_AAAA
:
561 rec
= AAAARecord(data
)
562 elif record_type
== dnsp
.DNS_TYPE_PTR
:
563 rec
= PTRRecord(data
)
564 elif record_type
== dnsp
.DNS_TYPE_CNAME
:
565 rec
= CNameRecord(data
)
566 elif record_type
== dnsp
.DNS_TYPE_NS
:
568 elif record_type
== dnsp
.DNS_TYPE_MX
:
569 tmp
= data
.split(' ')
571 raise CommandError('Data requires 2 elements - mail_server, preference')
573 preference
= int(tmp
[1])
574 rec
= MXRecord(mail_server
, preference
)
575 elif record_type
== dnsp
.DNS_TYPE_SRV
:
576 tmp
= data
.split(' ')
578 raise CommandError('Data requires 4 elements - server, port, priority, weight')
581 priority
= int(tmp
[2])
583 rec
= SRVRecord(server
, port
, priority
=priority
, weight
=weight
)
584 elif record_type
== dnsp
.DNS_TYPE_SOA
:
585 tmp
= data
.split(' ')
587 raise CommandError('Data requires 7 elements - nameserver, email, serial, '
588 'refresh, retry, expire, minimumttl')
592 refresh
= int(tmp
[3])
595 minimum
= int(tmp
[6])
596 rec
= SOARecord(nameserver
, email
, serial
=serial
, refresh
=refresh
,
597 retry
=retry
, expire
=expire
, minimum
=minimum
)
598 elif record_type
== dnsp
.DNS_TYPE_TXT
:
599 slist
= shlex
.split(data
)
600 rec
= TXTRecord(slist
)
602 raise CommandError('Unsupported record type')
606 # Match dns name (of type DNS_RPC_NAME)
607 def dns_name_equal(n1
, n2
):
608 return n1
.str.rstrip('.').lower() == n2
.str.rstrip('.').lower()
611 # Match a dns record with specified data
612 def dns_record_match(dns_conn
, server
, zone
, name
, record_type
, data
):
613 urec
= data_to_dns_record(record_type
, data
)
615 select_flags
= dnsserver
.DNS_RPC_VIEW_AUTHORITY_DATA
618 buflen
, res
= dns_conn
.DnssrvEnumRecords2(
619 dnsserver
.DNS_CLIENT_VERSION_LONGHORN
, 0, server
, zone
, name
, None,
620 record_type
, select_flags
, None, None)
621 except RuntimeError, e
:
624 if not res
or res
.count
== 0:
628 for rec
in res
.rec
[0].records
:
629 if rec
.wType
!= record_type
:
633 if record_type
== dnsp
.DNS_TYPE_A
:
634 if rec
.data
== urec
.data
:
636 elif record_type
== dnsp
.DNS_TYPE_AAAA
:
637 if rec
.data
== urec
.data
:
639 elif record_type
== dnsp
.DNS_TYPE_PTR
:
640 if dns_name_equal(rec
.data
, urec
.data
):
642 elif record_type
== dnsp
.DNS_TYPE_CNAME
:
643 if dns_name_equal(rec
.data
, urec
.data
):
645 elif record_type
== dnsp
.DNS_TYPE_NS
:
646 if dns_name_equal(rec
.data
, urec
.data
):
648 elif record_type
== dnsp
.DNS_TYPE_MX
:
649 if dns_name_equal(rec
.data
.nameExchange
, urec
.data
.nameExchange
) and \
650 rec
.data
.wPreference
== urec
.data
.wPreference
:
652 elif record_type
== dnsp
.DNS_TYPE_SRV
:
653 if rec
.data
.wPriority
== urec
.data
.wPriority
and \
654 rec
.data
.wWeight
== urec
.data
.wWeight
and \
655 rec
.data
.wPort
== urec
.data
.wPort
and \
656 dns_name_equal(rec
.data
.nameTarget
, urec
.data
.nameTarget
):
658 elif record_type
== dnsp
.DNS_TYPE_SOA
:
659 if rec
.data
.dwSerialNo
== urec
.data
.dwSerialNo
and \
660 rec
.data
.dwRefresh
== urec
.data
.dwRefresh
and \
661 rec
.data
.dwRetry
== urec
.data
.dwRetry
and \
662 rec
.data
.dwExpire
== urec
.data
.dwExpire
and \
663 rec
.data
.dwMinimumTtl
== urec
.data
.dwMinimumTtl
and \
664 dns_name_equal(rec
.data
.NamePrimaryServer
,
665 urec
.data
.NamePrimaryServer
) and \
666 dns_name_equal(rec
.data
.ZoneAdministratorEmail
,
667 urec
.data
.ZoneAdministratorEmail
):
669 elif record_type
== dnsp
.DNS_TYPE_TXT
:
670 if rec
.data
.count
== urec
.data
.count
:
672 for i
in xrange(rec
.data
.count
):
674 (rec
.data
.str[i
].str == urec
.data
.str[i
].str)
683 class cmd_serverinfo(Command
):
684 """Query for Server information."""
686 synopsis
= '%prog <server> [options]'
688 takes_args
= [ 'server' ]
690 takes_optiongroups
= {
691 "sambaopts": options
.SambaOptions
,
692 "versionopts": options
.VersionOptions
,
693 "credopts": options
.CredentialsOptions
,
697 Option('--client-version', help='Client Version',
698 default
='longhorn', metavar
='w2k|dotnet|longhorn',
699 choices
=['w2k','dotnet','longhorn'], dest
='cli_ver'),
702 def run(self
, server
, cli_ver
, sambaopts
=None, credopts
=None,
704 self
.lp
= sambaopts
.get_loadparm()
705 self
.creds
= credopts
.get_credentials(self
.lp
)
706 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
708 client_version
= dns_client_version(cli_ver
)
710 typeid
, res
= dns_conn
.DnssrvQuery2(client_version
, 0, server
,
712 print_serverinfo(self
.outf
, typeid
, res
)
715 class cmd_zoneinfo(Command
):
716 """Query for zone information."""
718 synopsis
= '%prog <server> <zone> [options]'
720 takes_args
= [ 'server', 'zone' ]
722 takes_optiongroups
= {
723 "sambaopts": options
.SambaOptions
,
724 "versionopts": options
.VersionOptions
,
725 "credopts": options
.CredentialsOptions
,
729 Option('--client-version', help='Client Version',
730 default
='longhorn', metavar
='w2k|dotnet|longhorn',
731 choices
=['w2k','dotnet','longhorn'], dest
='cli_ver'),
734 def run(self
, server
, zone
, cli_ver
, sambaopts
=None, credopts
=None,
736 self
.lp
= sambaopts
.get_loadparm()
737 self
.creds
= credopts
.get_credentials(self
.lp
)
738 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
740 client_version
= dns_client_version(cli_ver
)
742 typeid
, res
= dns_conn
.DnssrvQuery2(client_version
, 0, server
, zone
,
744 print_zoneinfo(self
.outf
, typeid
, res
)
747 class cmd_zonelist(Command
):
748 """Query for zones."""
750 synopsis
= '%prog <server> [options]'
752 takes_args
= [ 'server' ]
754 takes_optiongroups
= {
755 "sambaopts": options
.SambaOptions
,
756 "versionopts": options
.VersionOptions
,
757 "credopts": options
.CredentialsOptions
,
761 Option('--client-version', help='Client Version',
762 default
='longhorn', metavar
='w2k|dotnet|longhorn',
763 choices
=['w2k','dotnet','longhorn'], dest
='cli_ver'),
764 Option('--primary', help='List primary zones (default)',
765 action
='store_true', dest
='primary'),
766 Option('--secondary', help='List secondary zones',
767 action
='store_true', dest
='secondary'),
768 Option('--cache', help='List cached zones',
769 action
='store_true', dest
='cache'),
770 Option('--auto', help='List automatically created zones',
771 action
='store_true', dest
='auto'),
772 Option('--forward', help='List forward zones',
773 action
='store_true', dest
='forward'),
774 Option('--reverse', help='List reverse zones',
775 action
='store_true', dest
='reverse'),
776 Option('--ds', help='List directory integrated zones',
777 action
='store_true', dest
='ds'),
778 Option('--non-ds', help='List non-directory zones',
779 action
='store_true', dest
='nonds')
782 def run(self
, server
, cli_ver
, primary
=False, secondary
=False, cache
=False,
783 auto
=False, forward
=False, reverse
=False, ds
=False, nonds
=False,
784 sambaopts
=None, credopts
=None, versionopts
=None):
788 request_filter |
= dnsserver
.DNS_ZONE_REQUEST_PRIMARY
790 request_filter |
= dnsserver
.DNS_ZONE_REQUEST_SECONDARY
792 request_filter |
= dnsserver
.DNS_ZONE_REQUEST_CACHE
794 request_filter |
= dnsserver
.DNS_ZONE_REQUEST_AUTO
796 request_filter |
= dnsserver
.DNS_ZONE_REQUEST_FORWARD
798 request_filter |
= dnsserver
.DNS_ZONE_REQUEST_REVERSE
800 request_filter |
= dnsserver
.DNS_ZONE_REQUEST_DS
802 request_filter |
= dnsserver
.DNS_ZONE_REQUEST_NON_DS
804 if request_filter
== 0:
805 request_filter
= dnsserver
.DNS_ZONE_REQUEST_PRIMARY
807 self
.lp
= sambaopts
.get_loadparm()
808 self
.creds
= credopts
.get_credentials(self
.lp
)
809 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
811 client_version
= dns_client_version(cli_ver
)
813 typeid
, res
= dns_conn
.DnssrvComplexOperation2(client_version
,
816 dnsserver
.DNSSRV_TYPEID_DWORD
,
819 if client_version
== dnsserver
.DNS_CLIENT_VERSION_W2K
:
820 typeid
= dnsserver
.DNSSRV_TYPEID_ZONE_W2K
822 typeid
= dnsserver
.DNSSRV_TYPEID_ZONE
823 print_enumzones(self
.outf
, typeid
, res
)
826 class cmd_zonecreate(Command
):
829 synopsis
= '%prog <server> <zone> [options]'
831 takes_args
= [ 'server', 'zone' ]
833 takes_optiongroups
= {
834 "sambaopts": options
.SambaOptions
,
835 "versionopts": options
.VersionOptions
,
836 "credopts": options
.CredentialsOptions
,
840 Option('--client-version', help='Client Version',
841 default
='longhorn', metavar
='w2k|dotnet|longhorn',
842 choices
=['w2k','dotnet','longhorn'], dest
='cli_ver')
845 def run(self
, server
, zone
, cli_ver
, sambaopts
=None, credopts
=None,
848 self
.lp
= sambaopts
.get_loadparm()
849 self
.creds
= credopts
.get_credentials(self
.lp
)
850 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
854 client_version
= dns_client_version(cli_ver
)
855 if client_version
== dnsserver
.DNS_CLIENT_VERSION_W2K
:
856 typeid
= dnsserver
.DNSSRV_TYPEID_ZONE_CREATE_W2K
857 zone_create_info
= dnsserver
.DNS_RPC_ZONE_CREATE_INFO_W2K()
858 zone_create_info
.pszZoneName
= zone
859 zone_create_info
.dwZoneType
= dnsp
.DNS_ZONE_TYPE_PRIMARY
860 zone_create_info
.fAging
= 0
861 zone_create_info
.fDsIntegrated
= 1
862 zone_create_info
.fLoadExisting
= 1
863 elif client_version
== dnsserver
.DNS_CLIENT_VERSION_DOTNET
:
864 typeid
= dnsserver
.DNSSRV_TYPEID_ZONE_CREATE_DOTNET
865 zone_create_info
= dnsserver
.DNS_RPC_ZONE_CREATE_INFO_DOTNET()
866 zone_create_info
.pszZoneName
= zone
867 zone_create_info
.dwZoneType
= dnsp
.DNS_ZONE_TYPE_PRIMARY
868 zone_create_info
.fAging
= 0
869 zone_create_info
.fDsIntegrated
= 1
870 zone_create_info
.fLoadExisting
= 1
871 zone_create_info
.dwDpFlags
= dnsserver
.DNS_DP_DOMAIN_DEFAULT
873 typeid
= dnsserver
.DNSSRV_TYPEID_ZONE_CREATE
874 zone_create_info
= dnsserver
.DNS_RPC_ZONE_CREATE_INFO_LONGHORN()
875 zone_create_info
.pszZoneName
= zone
876 zone_create_info
.dwZoneType
= dnsp
.DNS_ZONE_TYPE_PRIMARY
877 zone_create_info
.fAging
= 0
878 zone_create_info
.fDsIntegrated
= 1
879 zone_create_info
.fLoadExisting
= 1
880 zone_create_info
.dwDpFlags
= dnsserver
.DNS_DP_DOMAIN_DEFAULT
882 res
= dns_conn
.DnssrvOperation2(client_version
, 0, server
, None,
883 0, 'ZoneCreate', typeid
,
886 typeid
= dnsserver
.DNSSRV_TYPEID_NAME_AND_PARAM
887 name_and_param
= dnsserver
.DNS_RPC_NAME_AND_PARAM()
888 name_and_param
.pszNodeName
= 'AllowUpdate'
889 name_and_param
.dwParam
= dnsp
.DNS_ZONE_UPDATE_SECURE
891 res
= dns_conn
.DnssrvOperation2(client_version
, 0, server
, zone
,
892 0, 'ResetDwordProperty', typeid
,
894 self
.outf
.write('Zone %s created successfully\n' % zone
)
897 class cmd_zonedelete(Command
):
900 synopsis
= '%prog <server> <zone> [options]'
902 takes_args
= [ 'server', 'zone' ]
904 takes_optiongroups
= {
905 "sambaopts": options
.SambaOptions
,
906 "versionopts": options
.VersionOptions
,
907 "credopts": options
.CredentialsOptions
,
910 def run(self
, server
, zone
, sambaopts
=None, credopts
=None,
913 self
.lp
= sambaopts
.get_loadparm()
914 self
.creds
= credopts
.get_credentials(self
.lp
)
915 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
918 res
= dns_conn
.DnssrvOperation2(dnsserver
.DNS_CLIENT_VERSION_LONGHORN
,
919 0, server
, zone
, 0, 'DeleteZoneFromDs',
920 dnsserver
.DNSSRV_TYPEID_NULL
,
922 self
.outf
.write('Zone %s delete successfully\n' % zone
)
925 class cmd_query(Command
):
928 synopsis
= '%prog <server> <zone> <name> <A|AAAA|CNAME|MX|NS|SOA|SRV|TXT|ALL> [options]'
930 takes_args
= [ 'server', 'zone', 'name', 'rtype' ]
932 takes_optiongroups
= {
933 "sambaopts": options
.SambaOptions
,
934 "versionopts": options
.VersionOptions
,
935 "credopts": options
.CredentialsOptions
,
939 Option('--authority', help='Search authoritative records (default)',
940 action
='store_true', dest
='authority'),
941 Option('--cache', help='Search cached records',
942 action
='store_true', dest
='cache'),
943 Option('--glue', help='Search glue records',
944 action
='store_true', dest
='glue'),
945 Option('--root', help='Search root hints',
946 action
='store_true', dest
='root'),
947 Option('--additional', help='List additional records',
948 action
='store_true', dest
='additional'),
949 Option('--no-children', help='Do not list children',
950 action
='store_true', dest
='no_children'),
951 Option('--only-children', help='List only children',
952 action
='store_true', dest
='only_children')
955 def run(self
, server
, zone
, name
, rtype
, authority
=False, cache
=False,
956 glue
=False, root
=False, additional
=False, no_children
=False,
957 only_children
=False, sambaopts
=None, credopts
=None,
959 record_type
= dns_type_flag(rtype
)
961 if name
.find('*') != -1:
962 raise CommandError('Wildcard searches not supported. To dump entire zone use "@"')
966 select_flags |
= dnsserver
.DNS_RPC_VIEW_AUTHORITY_DATA
968 select_flags |
= dnsserver
.DNS_RPC_VIEW_CACHE_DATA
970 select_flags |
= dnsserver
.DNS_RPC_VIEW_GLUE_DATA
972 select_flags |
= dnsserver
.DNS_RPC_VIEW_ROOT_HINT_DATA
974 select_flags |
= dnsserver
.DNS_RPC_VIEW_ADDITIONAL_DATA
976 select_flags |
= dnsserver
.DNS_RPC_VIEW_NO_CHILDREN
978 select_flags |
= dnsserver
.DNS_RPC_VIEW_ONLY_CHILDREN
980 if select_flags
== 0:
981 select_flags
= dnsserver
.DNS_RPC_VIEW_AUTHORITY_DATA
983 if select_flags
== dnsserver
.DNS_RPC_VIEW_ADDITIONAL_DATA
:
984 self
.outf
.write('Specify either --authority or --root along with --additional.\n')
985 self
.outf
.write('Assuming --authority.\n')
986 select_flags |
= dnsserver
.DNS_RPC_VIEW_AUTHORITY_DATA
988 self
.lp
= sambaopts
.get_loadparm()
989 self
.creds
= credopts
.get_credentials(self
.lp
)
990 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
992 buflen
, res
= dns_conn
.DnssrvEnumRecords2(
993 dnsserver
.DNS_CLIENT_VERSION_LONGHORN
, 0, server
, zone
, name
,
994 None, record_type
, select_flags
, None, None)
995 print_dnsrecords(self
.outf
, res
)
998 class cmd_roothints(Command
):
999 """Query root hints."""
1001 synopsis
= '%prog <server> [<name>] [options]'
1003 takes_args
= [ 'server', 'name?' ]
1005 takes_optiongroups
= {
1006 "sambaopts": options
.SambaOptions
,
1007 "versionopts": options
.VersionOptions
,
1008 "credopts": options
.CredentialsOptions
,
1011 def run(self
, server
, name
='.', sambaopts
=None, credopts
=None,
1013 record_type
= dnsp
.DNS_TYPE_NS
1014 select_flags
= (dnsserver
.DNS_RPC_VIEW_ROOT_HINT_DATA |
1015 dnsserver
.DNS_RPC_VIEW_ADDITIONAL_DATA
)
1017 self
.lp
= sambaopts
.get_loadparm()
1018 self
.creds
= credopts
.get_credentials(self
.lp
)
1019 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
1021 buflen
, res
= dns_conn
.DnssrvEnumRecords2(
1022 dnsserver
.DNS_CLIENT_VERSION_LONGHORN
, 0, server
, '..RootHints',
1023 name
, None, record_type
, select_flags
, None, None)
1024 print_dnsrecords(self
.outf
, res
)
1027 class cmd_add_record(Command
):
1030 For each type data contents are as follows:
1031 A ipv4_address_string
1032 AAAA ipv6_address_string
1036 MX "fqdn_string preference"
1037 SRV "fqdn_string port priority weight"
1038 TXT "'string1' 'string2' ..."
1041 synopsis
= '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SRV|TXT> <data>'
1043 takes_args
= [ 'server', 'zone', 'name', 'rtype', 'data' ]
1045 takes_optiongroups
= {
1046 "sambaopts": options
.SambaOptions
,
1047 "versionopts": options
.VersionOptions
,
1048 "credopts": options
.CredentialsOptions
,
1051 def run(self
, server
, zone
, name
, rtype
, data
, sambaopts
=None,
1052 credopts
=None, versionopts
=None):
1054 if rtype
.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SRV','TXT'):
1055 raise CommandError('Adding record of type %s is not supported' % rtype
)
1057 record_type
= dns_type_flag(rtype
)
1058 rec
= data_to_dns_record(record_type
, data
)
1060 self
.lp
= sambaopts
.get_loadparm()
1061 self
.creds
= credopts
.get_credentials(self
.lp
)
1062 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
1064 rec_match
= dns_record_match(dns_conn
, server
, zone
, name
, record_type
,
1066 if rec_match
is not None:
1067 raise CommandError('Record already exists')
1069 add_rec_buf
= dnsserver
.DNS_RPC_RECORD_BUF()
1070 add_rec_buf
.rec
= rec
1072 dns_conn
.DnssrvUpdateRecord2(dnsserver
.DNS_CLIENT_VERSION_LONGHORN
,
1073 0, server
, zone
, name
, add_rec_buf
, None)
1074 self
.outf
.write('Record added successfully\n')
1077 class cmd_update_record(Command
):
1078 """Update a DNS record
1080 For each type data contents are as follows:
1081 A ipv4_address_string
1082 AAAA ipv6_address_string
1086 MX "fqdn_string preference"
1087 SOA "fqdn_dns fqdn_email serial refresh retry expire minimumttl"
1088 SRV "fqdn_string port priority weight"
1089 TXT "'string1' 'string2' ..."
1092 synopsis
= '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SOA|SRV|TXT> <olddata> <newdata>'
1094 takes_args
= [ 'server', 'zone', 'name', 'rtype', 'olddata', 'newdata' ]
1096 takes_optiongroups
= {
1097 "sambaopts": options
.SambaOptions
,
1098 "versionopts": options
.VersionOptions
,
1099 "credopts": options
.CredentialsOptions
,
1102 def run(self
, server
, zone
, name
, rtype
, olddata
, newdata
,
1103 sambaopts
=None, credopts
=None, versionopts
=None):
1105 if rtype
.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SOA','SRV','TXT'):
1106 raise CommandError('Updating record of type %s is not supported' % rtype
)
1108 record_type
= dns_type_flag(rtype
)
1109 rec
= data_to_dns_record(record_type
, newdata
)
1111 self
.lp
= sambaopts
.get_loadparm()
1112 self
.creds
= credopts
.get_credentials(self
.lp
)
1113 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
1115 rec_match
= dns_record_match(dns_conn
, server
, zone
, name
, record_type
,
1118 raise CommandError('Record does not exist')
1120 # Copy properties from existing record to new record
1121 rec
.dwFlags
= rec_match
.dwFlags
1122 rec
.dwSerial
= rec_match
.dwSerial
1123 rec
.dwTtlSeconds
= rec_match
.dwTtlSeconds
1124 rec
.dwTimeStamp
= rec_match
.dwTimeStamp
1126 add_rec_buf
= dnsserver
.DNS_RPC_RECORD_BUF()
1127 add_rec_buf
.rec
= rec
1129 del_rec_buf
= dnsserver
.DNS_RPC_RECORD_BUF()
1130 del_rec_buf
.rec
= rec_match
1132 dns_conn
.DnssrvUpdateRecord2(dnsserver
.DNS_CLIENT_VERSION_LONGHORN
,
1139 self
.outf
.write('Record updated successfully\n')
1142 class cmd_delete_record(Command
):
1143 """Delete a DNS record
1145 For each type data contents are as follows:
1146 A ipv4_address_string
1147 AAAA ipv6_address_string
1151 MX "fqdn_string preference"
1152 SRV "fqdn_string port priority weight"
1153 TXT "'string1' 'string2' ..."
1156 synopsis
= '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SRV|TXT> <data>'
1158 takes_args
= [ 'server', 'zone', 'name', 'rtype', 'data' ]
1160 takes_optiongroups
= {
1161 "sambaopts": options
.SambaOptions
,
1162 "versionopts": options
.VersionOptions
,
1163 "credopts": options
.CredentialsOptions
,
1166 def run(self
, server
, zone
, name
, rtype
, data
, sambaopts
=None, credopts
=None, versionopts
=None):
1168 if rtype
.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SRV','TXT'):
1169 raise CommandError('Deleting record of type %s is not supported' % rtype
)
1171 record_type
= dns_type_flag(rtype
)
1173 self
.lp
= sambaopts
.get_loadparm()
1174 self
.creds
= credopts
.get_credentials(self
.lp
)
1175 dns_conn
= dns_connect(server
, self
.lp
, self
.creds
)
1177 rec_match
= dns_record_match(dns_conn
, server
, zone
, name
, record_type
, data
)
1179 raise CommandError('Record does not exist')
1181 del_rec_buf
= dnsserver
.DNS_RPC_RECORD_BUF()
1182 del_rec_buf
.rec
= rec_match
1184 dns_conn
.DnssrvUpdateRecord2(dnsserver
.DNS_CLIENT_VERSION_LONGHORN
,
1191 self
.outf
.write('Record deleted successfully\n')
1194 class cmd_dns(SuperCommand
):
1195 """Domain Name Service (DNS) management."""
1198 subcommands
['serverinfo'] = cmd_serverinfo()
1199 subcommands
['zoneinfo'] = cmd_zoneinfo()
1200 subcommands
['zonelist'] = cmd_zonelist()
1201 subcommands
['zonecreate'] = cmd_zonecreate()
1202 subcommands
['zonedelete'] = cmd_zonedelete()
1203 subcommands
['query'] = cmd_query()
1204 subcommands
['roothints'] = cmd_roothints()
1205 subcommands
['add'] = cmd_add_record()
1206 subcommands
['update'] = cmd_update_record()
1207 subcommands
['delete'] = cmd_delete_record()