netcmd/dns: fix typo
[Samba/gebeck_regimport.git] / python / samba / netcmd / dns.py
blob309951d2d8407ece7a96cedfb61dae9b767545c1
1 # DNS management tool
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 import shlex
24 from samba.netcmd import (
25 Command,
26 CommandError,
27 Option,
28 SuperCommand,
30 from samba.dcerpc import dnsp, dnsserver
33 def dns_connect(server, lp, creds):
34 if server.lower() == 'localhost':
35 server = '127.0.0.1'
36 binding_str = "ncacn_ip_tcp:%s[sign]" % server
37 dns_conn = dnsserver.dnsserver(binding_str, lp, creds)
38 return dns_conn
41 def bool_string(flag):
42 if flag == 0:
43 ret = 'FALSE'
44 elif flag == 1:
45 ret = 'TRUE'
46 else:
47 ret = 'UNKNOWN (0x%x)' % flag
48 return ret
51 def enum_string(module, enum_defs, value):
52 ret = None
53 for e in enum_defs:
54 if value == getattr(module, e):
55 ret = e
56 break
57 if not ret:
58 ret = 'UNKNOWN (0x%x)' % value
59 return ret
62 def bitmap_string(module, bitmap_defs, value):
63 ret = ''
64 for b in bitmap_defs:
65 if value & getattr(module, b):
66 ret += '%s ' % b
67 if not ret:
68 ret = 'NONE'
69 return ret
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):
125 ret = []
126 if not array:
127 return ret
128 for i in xrange(array.AddrCount):
129 addr = '%s' % inet_ntoa(pack('i', array.AddrArray[i]))
130 ret.append(addr)
131 return ret
134 def dns_addr_array_string(array):
135 ret = []
136 if not array:
137 return ret
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]])
145 else:
146 addr = 'UNKNOWN'
147 ret.append(addr)
148 return ret
151 def dns_type_flag(rec_type):
152 rtype = rec_type.upper()
153 if rtype == 'A':
154 record_type = dnsp.DNS_TYPE_A
155 elif rtype == 'AAAA':
156 record_type = dnsp.DNS_TYPE_AAAA
157 elif rtype == 'PTR':
158 record_type = dnsp.DNS_TYPE_PTR
159 elif rtype == 'NS':
160 record_type = dnsp.DNS_TYPE_NS
161 elif rtype == 'CNAME':
162 record_type = dnsp.DNS_TYPE_CNAME
163 elif rtype == 'SOA':
164 record_type = dnsp.DNS_TYPE_SOA
165 elif rtype == 'MX':
166 record_type = dnsp.DNS_TYPE_MX
167 elif rtype == 'SRV':
168 record_type = dnsp.DNS_TYPE_SRV
169 elif rtype == 'TXT':
170 record_type = dnsp.DNS_TYPE_TXT
171 elif rtype == 'ALL':
172 record_type = dnsp.DNS_TYPE_ALL
173 else:
174 raise CommandError('Unknown type of DNS record %s' % rec_type)
175 return record_type
178 def dns_client_version(cli_version):
179 version = cli_version.upper()
180 if version == 'W2K':
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
186 else:
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))
207 else:
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))
276 else:
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))
286 else:
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))
300 else:
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))
311 else:
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:
342 outf.write('\n')
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' % (
359 rec.data.dwSerialNo,
360 rec.data.dwRefresh,
361 rec.data.dwRetry,
362 rec.data.dwExpire,
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)
373 else:
374 mesg = 'Unknown: '
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' % (
382 rec.dnsNodeName.str,
383 rec.wRecordCount,
384 rec.dwChildCount))
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,
396 node_flag=0):
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,
409 node_flag=0):
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._ip6_addr = ip6_addr[:]
416 self.data = self._ip6_addr
419 class PTRRecord(dnsserver.DNS_RPC_RECORD):
421 def __init__(self, ptr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
422 node_flag=0):
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
428 self._ptr = ptr[:]
429 ptr_name = dnsserver.DNS_RPC_NAME()
430 ptr_name.str = self._ptr
431 ptr_name.len = len(ptr)
432 self.data = ptr_name
435 class CNameRecord(dnsserver.DNS_RPC_RECORD):
437 def __init__(self, cname, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
438 node_flag=0):
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,
454 node_flag=0):
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)
464 self.data = ns
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)
481 self.data = mx
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
499 soa.dwRetry = retry
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)
505 self.data = soa
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
520 srv.wWeight = weight
521 srv.wPort = port
522 srv.nameTarget.str = self._target
523 srv.nameTarget.len = len(target)
524 self.data = srv
527 class TXTRecord(dnsserver.DNS_RPC_RECORD):
529 def __init__(self, slist, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
530 node_flag=0):
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
536 self._slist = []
537 for s in slist:
538 self._slist.append(s[:])
539 names = []
540 for s in self._slist:
541 name = dnsserver.DNS_RPC_NAME()
542 name.str = s
543 name.len = len(s)
544 names.append(name)
545 txt = dnsserver.DNS_RPC_RECORD_STRING()
546 txt.count = len(slist)
547 txt.str = names
548 self.data = txt
551 # Convert data into a dns record
552 def data_to_dns_record(record_type, data):
553 if record_type == dnsp.DNS_TYPE_A:
554 rec = ARecord(data)
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:
562 rec = NSRecord(data)
563 elif record_type == dnsp.DNS_TYPE_MX:
564 tmp = data.split(' ')
565 if len(tmp) != 2:
566 raise CommandError('Data requires 2 elements - mail_server, preference')
567 mail_server = tmp[0]
568 preference = int(tmp[1])
569 rec = MXRecord(mail_server, preference)
570 elif record_type == dnsp.DNS_TYPE_SRV:
571 tmp = data.split(' ')
572 if len(tmp) != 4:
573 raise CommandError('Data requires 4 elements - server, port, priority, weight')
574 server = tmp[0]
575 port = int(tmp[1])
576 priority = int(tmp[2])
577 weight = int(tmp[3])
578 rec = SRVRecord(server, port, priority=priority, weight=weight)
579 elif record_type == dnsp.DNS_TYPE_SOA:
580 tmp = data.split(' ')
581 if len(tmp) != 7:
582 raise CommandError('Data requires 7 elements - nameserver, email, serial, '
583 'refresh, retry, expire, minimumttl')
584 nameserver = tmp[0]
585 email = tmp[1]
586 serial = int(tmp[2])
587 refresh = int(tmp[3])
588 retry = int(tmp[4])
589 expire = int(tmp[5])
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)
596 else:
597 raise CommandError('Unsupported record type')
598 return rec
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
612 try:
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:
617 return None
619 if not res or res.count == 0:
620 return None
622 rec_match = None
623 for rec in res.rec[0].records:
624 if rec.wType != record_type:
625 continue
627 found = False
628 if record_type == dnsp.DNS_TYPE_A:
629 if rec.data == urec.data:
630 found = True
631 elif record_type == dnsp.DNS_TYPE_AAAA:
632 if rec.data == urec.data:
633 found = True
634 elif record_type == dnsp.DNS_TYPE_PTR:
635 if dns_name_equal(rec.data, urec.data):
636 found = True
637 elif record_type == dnsp.DNS_TYPE_CNAME:
638 if dns_name_equal(rec.data, urec.data):
639 found = True
640 elif record_type == dnsp.DNS_TYPE_NS:
641 if dns_name_equal(rec.data, urec.data):
642 found = True
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:
646 found = True
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):
652 found = True
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):
663 found = True
664 elif record_type == dnsp.DNS_TYPE_TXT:
665 if rec.data.count == urec.data.count:
666 found = True
667 for i in xrange(rec.data.count):
668 found = found and \
669 (rec.data.str[i].str == urec.data.str[i].str)
671 if found:
672 rec_match = rec
673 break
675 return rec_match
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,
691 takes_options = [
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,
698 versionopts=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,
706 None, 'ServerInfo')
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,
723 takes_options = [
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,
730 versionopts=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,
738 'ZoneInfo')
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,
755 takes_options = [
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):
780 request_filter = 0
782 if primary:
783 request_filter |= dnsserver.DNS_ZONE_REQUEST_PRIMARY
784 if secondary:
785 request_filter |= dnsserver.DNS_ZONE_REQUEST_SECONDARY
786 if cache:
787 request_filter |= dnsserver.DNS_ZONE_REQUEST_CACHE
788 if auto:
789 request_filter |= dnsserver.DNS_ZONE_REQUEST_AUTO
790 if forward:
791 request_filter |= dnsserver.DNS_ZONE_REQUEST_FORWARD
792 if reverse:
793 request_filter |= dnsserver.DNS_ZONE_REQUEST_REVERSE
794 if ds:
795 request_filter |= dnsserver.DNS_ZONE_REQUEST_DS
796 if nonds:
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,
809 0, server, None,
810 'EnumZones',
811 dnsserver.DNSSRV_TYPEID_DWORD,
812 request_filter)
814 if client_version == dnsserver.DNS_CLIENT_VERSION_W2K:
815 typeid = dnsserver.DNSSRV_TYPEID_ZONE_W2K
816 else:
817 typeid = dnsserver.DNSSRV_TYPEID_ZONE
818 print_enumzones(self.outf, typeid, res)
821 class cmd_zonecreate(Command):
822 """Create a zone."""
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,
834 takes_options = [
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,
841 versionopts=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)
847 zone = zone.lower()
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
865 else:
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,
876 zone_create_info)
877 self.outf.write('Zone %s created successfully\n' % zone)
880 class cmd_zonedelete(Command):
881 """Delete a zone."""
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,
894 versionopts=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)
900 zone = zone.lower()
901 res = dns_conn.DnssrvOperation2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
902 0, server, zone, 0, 'DeleteZoneFromDs',
903 dnsserver.DNSSRV_TYPEID_NULL,
904 None)
905 self.outf.write('Zone %s delete successfully\n' % zone)
908 class cmd_query(Command):
909 """Query a name."""
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,
921 takes_options = [
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,
941 versionopts=None):
942 record_type = dns_type_flag(rtype)
944 select_flags = 0
945 if authority:
946 select_flags |= dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
947 if cache:
948 select_flags |= dnsserver.DNS_RPC_VIEW_CACHE_DATA
949 if glue:
950 select_flags |= dnsserver.DNS_RPC_VIEW_GLUE_DATA
951 if root:
952 select_flags |= dnsserver.DNS_RPC_VIEW_ROOT_HINT_DATA
953 if additional:
954 select_flags |= dnsserver.DNS_RPC_VIEW_ADDITIONAL_DATA
955 if no_children:
956 select_flags |= dnsserver.DNS_RPC_VIEW_NO_CHILDREN
957 if only_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,
992 versionopts=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):
1008 """Add a DNS record
1010 For each type data contents are as follows:
1011 A ipv4_address_string
1012 AAAA ipv6_address_string
1013 PTR fqdn_string
1014 CNAME fqdn_string
1015 NS fqdn_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,
1045 data)
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
1063 PTR fqdn_string
1064 CNAME fqdn_string
1065 NS fqdn_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,
1095 olddata)
1096 if not rec_match:
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,
1113 server,
1114 zone,
1115 name,
1116 add_rec_buf,
1117 del_rec_buf)
1118 self.outf.write('Record updated successfully\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
1127 PTR fqdn_string
1128 CNAME fqdn_string
1129 NS fqdn_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)
1157 if not rec_match:
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,
1165 server,
1166 zone,
1167 name,
1168 None,
1169 del_rec_buf)
1170 self.outf.write('Record deleted successfully\n')
1173 class cmd_dns(SuperCommand):
1174 """Domain Name Service (DNS) management."""
1176 subcommands = {}
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()