samba-tool/dns: Set secure zone update flag after creating new zone
[Samba/gebeck_regimport.git] / python / samba / netcmd / dns.py
blob137cd989f0c5e41bb704956d13079a24e10d8439
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, minttl=%d, ns=%s, email=%s' % (
359 rec.data.dwSerialNo,
360 rec.data.dwRefresh,
361 rec.data.dwRetry,
362 rec.data.dwExpire,
363 rec.data.dwMinimumTtl,
364 rec.data.NamePrimaryServer.str,
365 rec.data.ZoneAdministratorEmail.str)
366 elif rec.wType == dnsp.DNS_TYPE_MX:
367 mesg = 'MX: %s (%d)' % (rec.data.nameExchange.str, rec.data.wPreference)
368 elif rec.wType == dnsp.DNS_TYPE_SRV:
369 mesg = 'SRV: %s (%d, %d, %d)' % (rec.data.nameTarget.str, rec.data.wPort,
370 rec.data.wPriority, rec.data.wWeight)
371 elif rec.wType == dnsp.DNS_TYPE_TXT:
372 slist = ['"%s"' % name.str for name in rec.data.str]
373 mesg = 'TXT: %s' % ','.join(slist)
374 else:
375 mesg = 'Unknown: '
376 outf.write(' %s (flags=%x, serial=%d, ttl=%d)\n' % (
377 mesg, rec.dwFlags, rec.dwSerial, rec.dwTtlSeconds))
380 def print_dnsrecords(outf, records):
381 for rec in records.rec:
382 outf.write(' Name=%s, Records=%d, Children=%d\n' % (
383 rec.dnsNodeName.str,
384 rec.wRecordCount,
385 rec.dwChildCount))
386 for dns_rec in rec.records:
387 print_dns_record(outf, dns_rec)
391 # Always create a copy of strings when creating DNS_RPC_RECORDs
392 # to overcome the bug in pidl generated python bindings.
395 class ARecord(dnsserver.DNS_RPC_RECORD):
396 def __init__(self, ip_addr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
397 node_flag=0):
398 super(ARecord, self).__init__()
399 self.wType = dnsp.DNS_TYPE_A
400 self.dwFlags = rank | node_flag
401 self.dwSerial = serial
402 self.dwTtlSeconds = ttl
403 self._ip_addr = ip_addr[:]
404 self.data = self._ip_addr
407 class AAAARecord(dnsserver.DNS_RPC_RECORD):
409 def __init__(self, ip6_addr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
410 node_flag=0):
411 super(AAAARecord, self).__init__()
412 self.wType = dnsp.DNS_TYPE_AAAA
413 self.dwFlags = rank | node_flag
414 self.dwSerial = serial
415 self.dwTtlSeconds = ttl
416 self._ip6_addr = ip6_addr[:]
417 self.data = self._ip6_addr
420 class PTRRecord(dnsserver.DNS_RPC_RECORD):
422 def __init__(self, ptr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
423 node_flag=0):
424 super(PTRRecord, self).__init__()
425 self.wType = dnsp.DNS_TYPE_PTR
426 self.dwFlags = rank | node_flag
427 self.dwSerial = serial
428 self.dwTtlSeconds = ttl
429 self._ptr = ptr[:]
430 ptr_name = dnsserver.DNS_RPC_NAME()
431 ptr_name.str = self._ptr
432 ptr_name.len = len(ptr)
433 self.data = ptr_name
436 class CNameRecord(dnsserver.DNS_RPC_RECORD):
438 def __init__(self, cname, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
439 node_flag=0):
440 super(CNameRecord, self).__init__()
441 self.wType = dnsp.DNS_TYPE_CNAME
442 self.dwFlags = rank | node_flag
443 self.dwSerial = serial
444 self.dwTtlSeconds = ttl
445 self._cname = cname[:]
446 cname_name = dnsserver.DNS_RPC_NAME()
447 cname_name.str = self._cname
448 cname_name.len = len(cname)
449 self.data = cname_name
452 class NSRecord(dnsserver.DNS_RPC_RECORD):
454 def __init__(self, dns_server, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
455 node_flag=0):
456 super(NSRecord, self).__init__()
457 self.wType = dnsp.DNS_TYPE_NS
458 self.dwFlags = rank | node_flag
459 self.dwSerial = serial
460 self.dwTtlSeconds = ttl
461 self._dns_server = dns_server[:]
462 ns = dnsserver.DNS_RPC_NAME()
463 ns.str = self._dns_server
464 ns.len = len(dns_server)
465 self.data = ns
468 class MXRecord(dnsserver.DNS_RPC_RECORD):
470 def __init__(self, mail_server, preference, serial=1, ttl=900,
471 rank=dnsp.DNS_RANK_ZONE, node_flag=0):
472 super(MXRecord, self).__init__()
473 self.wType = dnsp.DNS_TYPE_MX
474 self.dwFlags = rank | node_flag
475 self.dwSerial = serial
476 self.dwTtlSeconds = ttl
477 self._mail_server = mail_server[:]
478 mx = dnsserver.DNS_RPC_RECORD_NAME_PREFERENCE()
479 mx.wPreference = preference
480 mx.nameExchange.str = self._mail_server
481 mx.nameExchange.len = len(mail_server)
482 self.data = mx
485 class SOARecord(dnsserver.DNS_RPC_RECORD):
487 def __init__(self, mname, rname, serial=1, refresh=900, retry=600,
488 expire=86400, minimum=3600, ttl=3600, rank=dnsp.DNS_RANK_ZONE,
489 node_flag=dnsp.DNS_RPC_FLAG_AUTH_ZONE_ROOT):
490 super(SOARecord, self).__init__()
491 self.wType = dnsp.DNS_TYPE_SOA
492 self.dwFlags = rank | node_flag
493 self.dwSerial = serial
494 self.dwTtlSeconds = ttl
495 self._mname = mname[:]
496 self._rname = rname[:]
497 soa = dnsserver.DNS_RPC_RECORD_SOA()
498 soa.dwSerialNo = serial
499 soa.dwRefresh = refresh
500 soa.dwRetry = retry
501 soa.dwExpire = expire
502 soa.dwMinimumTtl = minimum
503 soa.NamePrimaryServer.str = self._mname
504 soa.NamePrimaryServer.len = len(mname)
505 soa.ZoneAdministratorEmail.str = self._rname
506 soa.ZoneAdministratorEmail.len = len(rname)
507 self.data = soa
510 class SRVRecord(dnsserver.DNS_RPC_RECORD):
512 def __init__(self, target, port, priority=0, weight=100, serial=1, ttl=900,
513 rank=dnsp.DNS_RANK_ZONE, node_flag=0):
514 super(SRVRecord, self).__init__()
515 self.wType = dnsp.DNS_TYPE_SRV
516 self.dwFlags = rank | node_flag
517 self.dwSerial = serial
518 self.dwTtlSeconds = ttl
519 self._target = target[:]
520 srv = dnsserver.DNS_RPC_RECORD_SRV()
521 srv.wPriority = priority
522 srv.wWeight = weight
523 srv.wPort = port
524 srv.nameTarget.str = self._target
525 srv.nameTarget.len = len(target)
526 self.data = srv
529 class TXTRecord(dnsserver.DNS_RPC_RECORD):
531 def __init__(self, slist, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
532 node_flag=0):
533 super(TXTRecord, self).__init__()
534 self.wType = dnsp.DNS_TYPE_TXT
535 self.dwFlags = rank | node_flag
536 self.dwSerial = serial
537 self.dwTtlSeconds = ttl
538 self._slist = []
539 for s in slist:
540 self._slist.append(s[:])
541 names = []
542 for s in self._slist:
543 name = dnsserver.DNS_RPC_NAME()
544 name.str = s
545 name.len = len(s)
546 names.append(name)
547 txt = dnsserver.DNS_RPC_RECORD_STRING()
548 txt.count = len(slist)
549 txt.str = names
550 self.data = txt
553 # Convert data into a dns record
554 def data_to_dns_record(record_type, data):
555 if record_type == dnsp.DNS_TYPE_A:
556 rec = ARecord(data)
557 elif record_type == dnsp.DNS_TYPE_AAAA:
558 rec = AAAARecord(data)
559 elif record_type == dnsp.DNS_TYPE_PTR:
560 rec = PTRRecord(data)
561 elif record_type == dnsp.DNS_TYPE_CNAME:
562 rec = CNameRecord(data)
563 elif record_type == dnsp.DNS_TYPE_NS:
564 rec = NSRecord(data)
565 elif record_type == dnsp.DNS_TYPE_MX:
566 tmp = data.split(' ')
567 if len(tmp) != 2:
568 raise CommandError('Data requires 2 elements - mail_server, preference')
569 mail_server = tmp[0]
570 preference = int(tmp[1])
571 rec = MXRecord(mail_server, preference)
572 elif record_type == dnsp.DNS_TYPE_SRV:
573 tmp = data.split(' ')
574 if len(tmp) != 4:
575 raise CommandError('Data requires 4 elements - server, port, priority, weight')
576 server = tmp[0]
577 port = int(tmp[1])
578 priority = int(tmp[2])
579 weight = int(tmp[3])
580 rec = SRVRecord(server, port, priority=priority, weight=weight)
581 elif record_type == dnsp.DNS_TYPE_SOA:
582 tmp = data.split(' ')
583 if len(tmp) != 7:
584 raise CommandError('Data requires 7 elements - nameserver, email, serial, '
585 'refresh, retry, expire, minimumttl')
586 nameserver = tmp[0]
587 email = tmp[1]
588 serial = int(tmp[2])
589 refresh = int(tmp[3])
590 retry = int(tmp[4])
591 expire = int(tmp[5])
592 minimum = int(tmp[6])
593 rec = SOARecord(nameserver, email, serial=serial, refresh=refresh,
594 retry=retry, expire=expire, minimum=minimum)
595 elif record_type == dnsp.DNS_TYPE_TXT:
596 slist = shlex.split(data)
597 rec = TXTRecord(slist)
598 else:
599 raise CommandError('Unsupported record type')
600 return rec
603 # Match dns name (of type DNS_RPC_NAME)
604 def dns_name_equal(n1, n2):
605 return n1.str.rstrip('.').lower() == n2.str.rstrip('.').lower()
608 # Match a dns record with specified data
609 def dns_record_match(dns_conn, server, zone, name, record_type, data):
610 urec = data_to_dns_record(record_type, data)
612 select_flags = dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
614 try:
615 buflen, res = dns_conn.DnssrvEnumRecords2(
616 dnsserver.DNS_CLIENT_VERSION_LONGHORN, 0, server, zone, name, None,
617 record_type, select_flags, None, None)
618 except RuntimeError, e:
619 return None
621 if not res or res.count == 0:
622 return None
624 rec_match = None
625 for rec in res.rec[0].records:
626 if rec.wType != record_type:
627 continue
629 found = False
630 if record_type == dnsp.DNS_TYPE_A:
631 if rec.data == urec.data:
632 found = True
633 elif record_type == dnsp.DNS_TYPE_AAAA:
634 if rec.data == urec.data:
635 found = True
636 elif record_type == dnsp.DNS_TYPE_PTR:
637 if dns_name_equal(rec.data, urec.data):
638 found = True
639 elif record_type == dnsp.DNS_TYPE_CNAME:
640 if dns_name_equal(rec.data, urec.data):
641 found = True
642 elif record_type == dnsp.DNS_TYPE_NS:
643 if dns_name_equal(rec.data, urec.data):
644 found = True
645 elif record_type == dnsp.DNS_TYPE_MX:
646 if dns_name_equal(rec.data.nameExchange, urec.data.nameExchange) and \
647 rec.data.wPreference == urec.data.wPreference:
648 found = True
649 elif record_type == dnsp.DNS_TYPE_SRV:
650 if rec.data.wPriority == urec.data.wPriority and \
651 rec.data.wWeight == urec.data.wWeight and \
652 rec.data.wPort == urec.data.wPort and \
653 dns_name_equal(rec.data.nameTarget, urec.data.nameTarget):
654 found = True
655 elif record_type == dnsp.DNS_TYPE_SOA:
656 if rec.data.dwSerialNo == urec.data.dwSerialNo and \
657 rec.data.dwRefresh == urec.data.dwRefresh and \
658 rec.data.dwRetry == urec.data.dwRetry and \
659 rec.data.dwExpire == urec.data.dwExpire and \
660 rec.data.dwMinimumTtl == urec.data.dwMinimumTtl and \
661 dns_name_equal(rec.data.NamePrimaryServer,
662 urec.data.NamePrimaryServer) and \
663 dns_name_equal(rec.data.ZoneAdministratorEmail,
664 urec.data.ZoneAdministratorEmail):
665 found = True
666 elif record_type == dnsp.DNS_TYPE_TXT:
667 if rec.data.count == urec.data.count:
668 found = True
669 for i in xrange(rec.data.count):
670 found = found and \
671 (rec.data.str[i].str == urec.data.str[i].str)
673 if found:
674 rec_match = rec
675 break
677 return rec_match
680 class cmd_serverinfo(Command):
681 """Query for Server information."""
683 synopsis = '%prog <server> [options]'
685 takes_args = [ 'server' ]
687 takes_optiongroups = {
688 "sambaopts": options.SambaOptions,
689 "versionopts": options.VersionOptions,
690 "credopts": options.CredentialsOptions,
693 takes_options = [
694 Option('--client-version', help='Client Version',
695 default='longhorn', metavar='w2k|dotnet|longhorn',
696 choices=['w2k','dotnet','longhorn'], dest='cli_ver'),
699 def run(self, server, cli_ver, sambaopts=None, credopts=None,
700 versionopts=None):
701 self.lp = sambaopts.get_loadparm()
702 self.creds = credopts.get_credentials(self.lp)
703 dns_conn = dns_connect(server, self.lp, self.creds)
705 client_version = dns_client_version(cli_ver)
707 typeid, res = dns_conn.DnssrvQuery2(client_version, 0, server,
708 None, 'ServerInfo')
709 print_serverinfo(self.outf, typeid, res)
712 class cmd_zoneinfo(Command):
713 """Query for zone information."""
715 synopsis = '%prog <server> <zone> [options]'
717 takes_args = [ 'server', 'zone' ]
719 takes_optiongroups = {
720 "sambaopts": options.SambaOptions,
721 "versionopts": options.VersionOptions,
722 "credopts": options.CredentialsOptions,
725 takes_options = [
726 Option('--client-version', help='Client Version',
727 default='longhorn', metavar='w2k|dotnet|longhorn',
728 choices=['w2k','dotnet','longhorn'], dest='cli_ver'),
731 def run(self, server, zone, cli_ver, sambaopts=None, credopts=None,
732 versionopts=None):
733 self.lp = sambaopts.get_loadparm()
734 self.creds = credopts.get_credentials(self.lp)
735 dns_conn = dns_connect(server, self.lp, self.creds)
737 client_version = dns_client_version(cli_ver)
739 typeid, res = dns_conn.DnssrvQuery2(client_version, 0, server, zone,
740 'ZoneInfo')
741 print_zoneinfo(self.outf, typeid, res)
744 class cmd_zonelist(Command):
745 """Query for zones."""
747 synopsis = '%prog <server> [options]'
749 takes_args = [ 'server' ]
751 takes_optiongroups = {
752 "sambaopts": options.SambaOptions,
753 "versionopts": options.VersionOptions,
754 "credopts": options.CredentialsOptions,
757 takes_options = [
758 Option('--client-version', help='Client Version',
759 default='longhorn', metavar='w2k|dotnet|longhorn',
760 choices=['w2k','dotnet','longhorn'], dest='cli_ver'),
761 Option('--primary', help='List primary zones (default)',
762 action='store_true', dest='primary'),
763 Option('--secondary', help='List secondary zones',
764 action='store_true', dest='secondary'),
765 Option('--cache', help='List cached zones',
766 action='store_true', dest='cache'),
767 Option('--auto', help='List automatically created zones',
768 action='store_true', dest='auto'),
769 Option('--forward', help='List forward zones',
770 action='store_true', dest='forward'),
771 Option('--reverse', help='List reverse zones',
772 action='store_true', dest='reverse'),
773 Option('--ds', help='List directory integrated zones',
774 action='store_true', dest='ds'),
775 Option('--non-ds', help='List non-directory zones',
776 action='store_true', dest='nonds')
779 def run(self, server, cli_ver, primary=False, secondary=False, cache=False,
780 auto=False, forward=False, reverse=False, ds=False, nonds=False,
781 sambaopts=None, credopts=None, versionopts=None):
782 request_filter = 0
784 if primary:
785 request_filter |= dnsserver.DNS_ZONE_REQUEST_PRIMARY
786 if secondary:
787 request_filter |= dnsserver.DNS_ZONE_REQUEST_SECONDARY
788 if cache:
789 request_filter |= dnsserver.DNS_ZONE_REQUEST_CACHE
790 if auto:
791 request_filter |= dnsserver.DNS_ZONE_REQUEST_AUTO
792 if forward:
793 request_filter |= dnsserver.DNS_ZONE_REQUEST_FORWARD
794 if reverse:
795 request_filter |= dnsserver.DNS_ZONE_REQUEST_REVERSE
796 if ds:
797 request_filter |= dnsserver.DNS_ZONE_REQUEST_DS
798 if nonds:
799 request_filter |= dnsserver.DNS_ZONE_REQUEST_NON_DS
801 if request_filter == 0:
802 request_filter = dnsserver.DNS_ZONE_REQUEST_PRIMARY
804 self.lp = sambaopts.get_loadparm()
805 self.creds = credopts.get_credentials(self.lp)
806 dns_conn = dns_connect(server, self.lp, self.creds)
808 client_version = dns_client_version(cli_ver)
810 typeid, res = dns_conn.DnssrvComplexOperation2(client_version,
811 0, server, None,
812 'EnumZones',
813 dnsserver.DNSSRV_TYPEID_DWORD,
814 request_filter)
816 if client_version == dnsserver.DNS_CLIENT_VERSION_W2K:
817 typeid = dnsserver.DNSSRV_TYPEID_ZONE_W2K
818 else:
819 typeid = dnsserver.DNSSRV_TYPEID_ZONE
820 print_enumzones(self.outf, typeid, res)
823 class cmd_zonecreate(Command):
824 """Create a zone."""
826 synopsis = '%prog <server> <zone> [options]'
828 takes_args = [ 'server', 'zone' ]
830 takes_optiongroups = {
831 "sambaopts": options.SambaOptions,
832 "versionopts": options.VersionOptions,
833 "credopts": options.CredentialsOptions,
836 takes_options = [
837 Option('--client-version', help='Client Version',
838 default='longhorn', metavar='w2k|dotnet|longhorn',
839 choices=['w2k','dotnet','longhorn'], dest='cli_ver')
842 def run(self, server, zone, cli_ver, sambaopts=None, credopts=None,
843 versionopts=None):
845 self.lp = sambaopts.get_loadparm()
846 self.creds = credopts.get_credentials(self.lp)
847 dns_conn = dns_connect(server, self.lp, self.creds)
849 zone = zone.lower()
851 client_version = dns_client_version(cli_ver)
852 if client_version == dnsserver.DNS_CLIENT_VERSION_W2K:
853 typeid = dnsserver.DNSSRV_TYPEID_ZONE_CREATE_W2K
854 zone_create_info = dnsserver.DNS_RPC_ZONE_CREATE_INFO_W2K()
855 zone_create_info.pszZoneName = zone
856 zone_create_info.dwZoneType = dnsp.DNS_ZONE_TYPE_PRIMARY
857 zone_create_info.fAging = 0
858 zone_create_info.fDsIntegrated = 1
859 zone_create_info.fLoadExisting = 1
860 elif client_version == dnsserver.DNS_CLIENT_VERSION_DOTNET:
861 typeid = dnsserver.DNSSRV_TYPEID_ZONE_CREATE_DOTNET
862 zone_create_info = dnsserver.DNS_RPC_ZONE_CREATE_INFO_DOTNET()
863 zone_create_info.pszZoneName = zone
864 zone_create_info.dwZoneType = dnsp.DNS_ZONE_TYPE_PRIMARY
865 zone_create_info.fAging = 0
866 zone_create_info.fDsIntegrated = 1
867 zone_create_info.fLoadExisting = 1
868 zone_create_info.dwDpFlags = dnsserver.DNS_DP_DOMAIN_DEFAULT
869 else:
870 typeid = dnsserver.DNSSRV_TYPEID_ZONE_CREATE
871 zone_create_info = dnsserver.DNS_RPC_ZONE_CREATE_INFO_LONGHORN()
872 zone_create_info.pszZoneName = zone
873 zone_create_info.dwZoneType = dnsp.DNS_ZONE_TYPE_PRIMARY
874 zone_create_info.fAging = 0
875 zone_create_info.fDsIntegrated = 1
876 zone_create_info.fLoadExisting = 1
877 zone_create_info.dwDpFlags = dnsserver.DNS_DP_DOMAIN_DEFAULT
879 res = dns_conn.DnssrvOperation2(client_version, 0, server, None,
880 0, 'ZoneCreate', typeid,
881 zone_create_info)
883 typeid = dnsserver.DNSSRV_TYPEID_NAME_AND_PARAM
884 name_and_param = dnsserver.DNS_RPC_NAME_AND_PARAM()
885 name_and_param.pszNodeName = 'AllowUpdate'
886 name_and_param.dwParam = dnsp.DNS_ZONE_UPDATE_SECURE
888 res = dns_conn.DnssrvOperation2(client_version, 0, server, zone,
889 0, 'ResetDwordProperty', typeid,
890 name_and_param)
891 self.outf.write('Zone %s created successfully\n' % zone)
894 class cmd_zonedelete(Command):
895 """Delete a zone."""
897 synopsis = '%prog <server> <zone> [options]'
899 takes_args = [ 'server', 'zone' ]
901 takes_optiongroups = {
902 "sambaopts": options.SambaOptions,
903 "versionopts": options.VersionOptions,
904 "credopts": options.CredentialsOptions,
907 def run(self, server, zone, sambaopts=None, credopts=None,
908 versionopts=None):
910 self.lp = sambaopts.get_loadparm()
911 self.creds = credopts.get_credentials(self.lp)
912 dns_conn = dns_connect(server, self.lp, self.creds)
914 zone = zone.lower()
915 res = dns_conn.DnssrvOperation2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
916 0, server, zone, 0, 'DeleteZoneFromDs',
917 dnsserver.DNSSRV_TYPEID_NULL,
918 None)
919 self.outf.write('Zone %s delete successfully\n' % zone)
922 class cmd_query(Command):
923 """Query a name."""
925 synopsis = '%prog <server> <zone> <name> <A|AAAA|CNAME|MX|NS|SOA|SRV|TXT|ALL> [options]'
927 takes_args = [ 'server', 'zone', 'name', 'rtype' ]
929 takes_optiongroups = {
930 "sambaopts": options.SambaOptions,
931 "versionopts": options.VersionOptions,
932 "credopts": options.CredentialsOptions,
935 takes_options = [
936 Option('--authority', help='Search authoritative records (default)',
937 action='store_true', dest='authority'),
938 Option('--cache', help='Search cached records',
939 action='store_true', dest='cache'),
940 Option('--glue', help='Search glue records',
941 action='store_true', dest='glue'),
942 Option('--root', help='Search root hints',
943 action='store_true', dest='root'),
944 Option('--additional', help='List additional records',
945 action='store_true', dest='additional'),
946 Option('--no-children', help='Do not list children',
947 action='store_true', dest='no_children'),
948 Option('--only-children', help='List only children',
949 action='store_true', dest='only_children')
952 def run(self, server, zone, name, rtype, authority=False, cache=False,
953 glue=False, root=False, additional=False, no_children=False,
954 only_children=False, sambaopts=None, credopts=None,
955 versionopts=None):
956 record_type = dns_type_flag(rtype)
958 select_flags = 0
959 if authority:
960 select_flags |= dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
961 if cache:
962 select_flags |= dnsserver.DNS_RPC_VIEW_CACHE_DATA
963 if glue:
964 select_flags |= dnsserver.DNS_RPC_VIEW_GLUE_DATA
965 if root:
966 select_flags |= dnsserver.DNS_RPC_VIEW_ROOT_HINT_DATA
967 if additional:
968 select_flags |= dnsserver.DNS_RPC_VIEW_ADDITIONAL_DATA
969 if no_children:
970 select_flags |= dnsserver.DNS_RPC_VIEW_NO_CHILDREN
971 if only_children:
972 select_flags |= dnsserver.DNS_RPC_VIEW_ONLY_CHILDREN
974 if select_flags == 0:
975 select_flags = dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
977 if select_flags == dnsserver.DNS_RPC_VIEW_ADDITIONAL_DATA:
978 self.outf.write('Specify either --authority or --root along with --additional.\n')
979 self.outf.write('Assuming --authority.\n')
980 select_flags |= dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
982 self.lp = sambaopts.get_loadparm()
983 self.creds = credopts.get_credentials(self.lp)
984 dns_conn = dns_connect(server, self.lp, self.creds)
986 buflen, res = dns_conn.DnssrvEnumRecords2(
987 dnsserver.DNS_CLIENT_VERSION_LONGHORN, 0, server, zone, name,
988 None, record_type, select_flags, None, None)
989 print_dnsrecords(self.outf, res)
992 class cmd_roothints(Command):
993 """Query root hints."""
995 synopsis = '%prog <server> [<name>] [options]'
997 takes_args = [ 'server', 'name?' ]
999 takes_optiongroups = {
1000 "sambaopts": options.SambaOptions,
1001 "versionopts": options.VersionOptions,
1002 "credopts": options.CredentialsOptions,
1005 def run(self, server, name='.', sambaopts=None, credopts=None,
1006 versionopts=None):
1007 record_type = dnsp.DNS_TYPE_NS
1008 select_flags = (dnsserver.DNS_RPC_VIEW_ROOT_HINT_DATA |
1009 dnsserver.DNS_RPC_VIEW_ADDITIONAL_DATA)
1011 self.lp = sambaopts.get_loadparm()
1012 self.creds = credopts.get_credentials(self.lp)
1013 dns_conn = dns_connect(server, self.lp, self.creds)
1015 buflen, res = dns_conn.DnssrvEnumRecords2(
1016 dnsserver.DNS_CLIENT_VERSION_LONGHORN, 0, server, '..RootHints',
1017 name, None, record_type, select_flags, None, None)
1018 print_dnsrecords(self.outf, res)
1021 class cmd_add_record(Command):
1022 """Add a DNS record
1024 For each type data contents are as follows:
1025 A ipv4_address_string
1026 AAAA ipv6_address_string
1027 PTR fqdn_string
1028 CNAME fqdn_string
1029 NS fqdn_string
1030 MX "fqdn_string preference"
1031 SRV "fqdn_string port priority weight"
1032 TXT "'string1' 'string2' ..."
1035 synopsis = '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SRV|TXT> <data>'
1037 takes_args = [ 'server', 'zone', 'name', 'rtype', 'data' ]
1039 takes_optiongroups = {
1040 "sambaopts": options.SambaOptions,
1041 "versionopts": options.VersionOptions,
1042 "credopts": options.CredentialsOptions,
1045 def run(self, server, zone, name, rtype, data, sambaopts=None,
1046 credopts=None, versionopts=None):
1048 if rtype.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SRV','TXT'):
1049 raise CommandError('Adding record of type %s is not supported' % rtype)
1051 record_type = dns_type_flag(rtype)
1052 rec = data_to_dns_record(record_type, data)
1054 self.lp = sambaopts.get_loadparm()
1055 self.creds = credopts.get_credentials(self.lp)
1056 dns_conn = dns_connect(server, self.lp, self.creds)
1058 rec_match = dns_record_match(dns_conn, server, zone, name, record_type,
1059 data)
1060 if rec_match is not None:
1061 raise CommandError('Record already exists')
1063 add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
1064 add_rec_buf.rec = rec
1066 dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
1067 0, server, zone, name, add_rec_buf, None)
1068 self.outf.write('Record added successfully\n')
1071 class cmd_update_record(Command):
1072 """Update a DNS record
1074 For each type data contents are as follows:
1075 A ipv4_address_string
1076 AAAA ipv6_address_string
1077 PTR fqdn_string
1078 CNAME fqdn_string
1079 NS fqdn_string
1080 MX "fqdn_string preference"
1081 SOA "fqdn_dns fqdn_email serial refresh retry expire minimumttl"
1082 SRV "fqdn_string port priority weight"
1083 TXT "'string1' 'string2' ..."
1086 synopsis = '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SOA|SRV|TXT> <olddata> <newdata>'
1088 takes_args = [ 'server', 'zone', 'name', 'rtype', 'olddata', 'newdata' ]
1090 takes_optiongroups = {
1091 "sambaopts": options.SambaOptions,
1092 "versionopts": options.VersionOptions,
1093 "credopts": options.CredentialsOptions,
1096 def run(self, server, zone, name, rtype, olddata, newdata,
1097 sambaopts=None, credopts=None, versionopts=None):
1099 if rtype.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SOA','SRV','TXT'):
1100 raise CommandError('Updating record of type %s is not supported' % rtype)
1102 record_type = dns_type_flag(rtype)
1103 rec = data_to_dns_record(record_type, newdata)
1105 self.lp = sambaopts.get_loadparm()
1106 self.creds = credopts.get_credentials(self.lp)
1107 dns_conn = dns_connect(server, self.lp, self.creds)
1109 rec_match = dns_record_match(dns_conn, server, zone, name, record_type,
1110 olddata)
1111 if not rec_match:
1112 raise CommandError('Record does not exist')
1114 # Copy properties from existing record to new record
1115 rec.dwFlags = rec_match.dwFlags
1116 rec.dwSerial = rec_match.dwSerial
1117 rec.dwTtlSeconds = rec_match.dwTtlSeconds
1118 rec.dwTimeStamp = rec_match.dwTimeStamp
1120 add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
1121 add_rec_buf.rec = rec
1123 del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
1124 del_rec_buf.rec = rec_match
1126 dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
1128 server,
1129 zone,
1130 name,
1131 add_rec_buf,
1132 del_rec_buf)
1133 self.outf.write('Record updated successfully\n')
1136 class cmd_delete_record(Command):
1137 """Delete a DNS record
1139 For each type data contents are as follows:
1140 A ipv4_address_string
1141 AAAA ipv6_address_string
1142 PTR fqdn_string
1143 CNAME fqdn_string
1144 NS fqdn_string
1145 MX "fqdn_string preference"
1146 SRV "fqdn_string port priority weight"
1147 TXT "'string1' 'string2' ..."
1150 synopsis = '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SRV|TXT> <data>'
1152 takes_args = [ 'server', 'zone', 'name', 'rtype', 'data' ]
1154 takes_optiongroups = {
1155 "sambaopts": options.SambaOptions,
1156 "versionopts": options.VersionOptions,
1157 "credopts": options.CredentialsOptions,
1160 def run(self, server, zone, name, rtype, data, sambaopts=None, credopts=None, versionopts=None):
1162 if rtype.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SRV','TXT'):
1163 raise CommandError('Deleting record of type %s is not supported' % rtype)
1165 record_type = dns_type_flag(rtype)
1167 self.lp = sambaopts.get_loadparm()
1168 self.creds = credopts.get_credentials(self.lp)
1169 dns_conn = dns_connect(server, self.lp, self.creds)
1171 rec_match = dns_record_match(dns_conn, server, zone, name, record_type, data)
1172 if not rec_match:
1173 raise CommandError('Record does not exist')
1175 del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
1176 del_rec_buf.rec = rec_match
1178 dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
1180 server,
1181 zone,
1182 name,
1183 None,
1184 del_rec_buf)
1185 self.outf.write('Record deleted successfully\n')
1188 class cmd_dns(SuperCommand):
1189 """Domain Name Service (DNS) management."""
1191 subcommands = {}
1192 subcommands['serverinfo'] = cmd_serverinfo()
1193 subcommands['zoneinfo'] = cmd_zoneinfo()
1194 subcommands['zonelist'] = cmd_zonelist()
1195 subcommands['zonecreate'] = cmd_zonecreate()
1196 subcommands['zonedelete'] = cmd_zonedelete()
1197 subcommands['query'] = cmd_query()
1198 subcommands['roothints'] = cmd_roothints()
1199 subcommands['add'] = cmd_add_record()
1200 subcommands['update'] = cmd_update_record()
1201 subcommands['delete'] = cmd_delete_record()