s4:rpc_server/lsa: notify winbindd about new trusted domains
[Samba.git] / python / samba / netcmd / dns.py
blob2cf9a1f13c554b5ac3f1507265ab256cb00755f2
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 from socket import inet_ntop
23 from socket import AF_INET
24 from socket import AF_INET6
25 import shlex
27 from samba.netcmd import (
28 Command,
29 CommandError,
30 Option,
31 SuperCommand,
33 from samba.dcerpc import dnsp, dnsserver
36 def dns_connect(server, lp, creds):
37 if server.lower() == 'localhost':
38 server = '127.0.0.1'
39 binding_str = "ncacn_ip_tcp:%s[sign]" % server
40 dns_conn = dnsserver.dnsserver(binding_str, lp, creds)
41 return dns_conn
44 def bool_string(flag):
45 if flag == 0:
46 ret = 'FALSE'
47 elif flag == 1:
48 ret = 'TRUE'
49 else:
50 ret = 'UNKNOWN (0x%x)' % flag
51 return ret
54 def enum_string(module, enum_defs, value):
55 ret = None
56 for e in enum_defs:
57 if value == getattr(module, e):
58 ret = e
59 break
60 if not ret:
61 ret = 'UNKNOWN (0x%x)' % value
62 return ret
65 def bitmap_string(module, bitmap_defs, value):
66 ret = ''
67 for b in bitmap_defs:
68 if value & getattr(module, b):
69 ret += '%s ' % b
70 if not ret:
71 ret = 'NONE'
72 return ret
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):
128 ret = []
129 if not array:
130 return ret
131 for i in xrange(array.AddrCount):
132 addr = inet_ntop(AF_INET, pack('I', array.AddrArray[i]))
133 ret.append(addr)
134 return ret
137 def dns_addr_array_string(array):
138 ret = []
139 if not array:
140 return ret
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)
148 else:
149 addr = 'UNKNOWN'
150 ret.append(addr)
151 return ret
154 def dns_type_flag(rec_type):
155 rtype = rec_type.upper()
156 if rtype == 'A':
157 record_type = dnsp.DNS_TYPE_A
158 elif rtype == 'AAAA':
159 record_type = dnsp.DNS_TYPE_AAAA
160 elif rtype == 'PTR':
161 record_type = dnsp.DNS_TYPE_PTR
162 elif rtype == 'NS':
163 record_type = dnsp.DNS_TYPE_NS
164 elif rtype == 'CNAME':
165 record_type = dnsp.DNS_TYPE_CNAME
166 elif rtype == 'SOA':
167 record_type = dnsp.DNS_TYPE_SOA
168 elif rtype == 'MX':
169 record_type = dnsp.DNS_TYPE_MX
170 elif rtype == 'SRV':
171 record_type = dnsp.DNS_TYPE_SRV
172 elif rtype == 'TXT':
173 record_type = dnsp.DNS_TYPE_TXT
174 elif rtype == 'ALL':
175 record_type = dnsp.DNS_TYPE_ALL
176 else:
177 raise CommandError('Unknown type of DNS record %s' % rec_type)
178 return record_type
181 def dns_client_version(cli_version):
182 version = cli_version.upper()
183 if version == 'W2K':
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
189 else:
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))
210 else:
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))
279 else:
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))
289 else:
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))
303 else:
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))
314 else:
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:
345 outf.write('\n')
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' % (
362 rec.data.dwSerialNo,
363 rec.data.dwRefresh,
364 rec.data.dwRetry,
365 rec.data.dwExpire,
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)
377 else:
378 mesg = 'Unknown: '
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' % (
386 rec.dnsNodeName.str,
387 rec.wRecordCount,
388 rec.dwChildCount))
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,
400 node_flag=0):
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,
413 node_flag=0):
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._ip6_addr = ip6_addr[:]
420 self.data = self._ip6_addr
423 class PTRRecord(dnsserver.DNS_RPC_RECORD):
425 def __init__(self, ptr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
426 node_flag=0):
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
432 self._ptr = ptr[:]
433 ptr_name = dnsserver.DNS_RPC_NAME()
434 ptr_name.str = self._ptr
435 ptr_name.len = len(ptr)
436 self.data = ptr_name
439 class CNameRecord(dnsserver.DNS_RPC_RECORD):
441 def __init__(self, cname, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
442 node_flag=0):
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,
458 node_flag=0):
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)
468 self.data = ns
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)
485 self.data = mx
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
503 soa.dwRetry = retry
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)
510 self.data = soa
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
525 srv.wWeight = weight
526 srv.wPort = port
527 srv.nameTarget.str = self._target
528 srv.nameTarget.len = len(target)
529 self.data = srv
532 class TXTRecord(dnsserver.DNS_RPC_RECORD):
534 def __init__(self, slist, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
535 node_flag=0):
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
541 self._slist = []
542 for s in slist:
543 self._slist.append(s[:])
544 names = []
545 for s in self._slist:
546 name = dnsserver.DNS_RPC_NAME()
547 name.str = s
548 name.len = len(s)
549 names.append(name)
550 txt = dnsserver.DNS_RPC_RECORD_STRING()
551 txt.count = len(slist)
552 txt.str = names
553 self.data = txt
556 # Convert data into a dns record
557 def data_to_dns_record(record_type, data):
558 if record_type == dnsp.DNS_TYPE_A:
559 rec = ARecord(data)
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:
567 rec = NSRecord(data)
568 elif record_type == dnsp.DNS_TYPE_MX:
569 tmp = data.split(' ')
570 if len(tmp) != 2:
571 raise CommandError('Data requires 2 elements - mail_server, preference')
572 mail_server = tmp[0]
573 preference = int(tmp[1])
574 rec = MXRecord(mail_server, preference)
575 elif record_type == dnsp.DNS_TYPE_SRV:
576 tmp = data.split(' ')
577 if len(tmp) != 4:
578 raise CommandError('Data requires 4 elements - server, port, priority, weight')
579 server = tmp[0]
580 port = int(tmp[1])
581 priority = int(tmp[2])
582 weight = int(tmp[3])
583 rec = SRVRecord(server, port, priority=priority, weight=weight)
584 elif record_type == dnsp.DNS_TYPE_SOA:
585 tmp = data.split(' ')
586 if len(tmp) != 7:
587 raise CommandError('Data requires 7 elements - nameserver, email, serial, '
588 'refresh, retry, expire, minimumttl')
589 nameserver = tmp[0]
590 email = tmp[1]
591 serial = int(tmp[2])
592 refresh = int(tmp[3])
593 retry = int(tmp[4])
594 expire = int(tmp[5])
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)
601 else:
602 raise CommandError('Unsupported record type')
603 return rec
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
617 try:
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:
622 return None
624 if not res or res.count == 0:
625 return None
627 rec_match = None
628 for rec in res.rec[0].records:
629 if rec.wType != record_type:
630 continue
632 found = False
633 if record_type == dnsp.DNS_TYPE_A:
634 if rec.data == urec.data:
635 found = True
636 elif record_type == dnsp.DNS_TYPE_AAAA:
637 if rec.data == urec.data:
638 found = True
639 elif record_type == dnsp.DNS_TYPE_PTR:
640 if dns_name_equal(rec.data, urec.data):
641 found = True
642 elif record_type == dnsp.DNS_TYPE_CNAME:
643 if dns_name_equal(rec.data, urec.data):
644 found = True
645 elif record_type == dnsp.DNS_TYPE_NS:
646 if dns_name_equal(rec.data, urec.data):
647 found = True
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:
651 found = True
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):
657 found = True
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):
668 found = True
669 elif record_type == dnsp.DNS_TYPE_TXT:
670 if rec.data.count == urec.data.count:
671 found = True
672 for i in xrange(rec.data.count):
673 found = found and \
674 (rec.data.str[i].str == urec.data.str[i].str)
676 if found:
677 rec_match = rec
678 break
680 return rec_match
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,
696 takes_options = [
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,
703 versionopts=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,
711 None, 'ServerInfo')
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,
728 takes_options = [
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,
735 versionopts=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,
743 'ZoneInfo')
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,
760 takes_options = [
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):
785 request_filter = 0
787 if primary:
788 request_filter |= dnsserver.DNS_ZONE_REQUEST_PRIMARY
789 if secondary:
790 request_filter |= dnsserver.DNS_ZONE_REQUEST_SECONDARY
791 if cache:
792 request_filter |= dnsserver.DNS_ZONE_REQUEST_CACHE
793 if auto:
794 request_filter |= dnsserver.DNS_ZONE_REQUEST_AUTO
795 if forward:
796 request_filter |= dnsserver.DNS_ZONE_REQUEST_FORWARD
797 if reverse:
798 request_filter |= dnsserver.DNS_ZONE_REQUEST_REVERSE
799 if ds:
800 request_filter |= dnsserver.DNS_ZONE_REQUEST_DS
801 if nonds:
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,
814 0, server, None,
815 'EnumZones',
816 dnsserver.DNSSRV_TYPEID_DWORD,
817 request_filter)
819 if client_version == dnsserver.DNS_CLIENT_VERSION_W2K:
820 typeid = dnsserver.DNSSRV_TYPEID_ZONE_W2K
821 else:
822 typeid = dnsserver.DNSSRV_TYPEID_ZONE
823 print_enumzones(self.outf, typeid, res)
826 class cmd_zonecreate(Command):
827 """Create a zone."""
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,
839 takes_options = [
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,
846 versionopts=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)
852 zone = zone.lower()
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
872 else:
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,
884 zone_create_info)
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,
893 name_and_param)
894 self.outf.write('Zone %s created successfully\n' % zone)
897 class cmd_zonedelete(Command):
898 """Delete a zone."""
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,
911 versionopts=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)
917 zone = zone.lower()
918 res = dns_conn.DnssrvOperation2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
919 0, server, zone, 0, 'DeleteZoneFromDs',
920 dnsserver.DNSSRV_TYPEID_NULL,
921 None)
922 self.outf.write('Zone %s delete successfully\n' % zone)
925 class cmd_query(Command):
926 """Query a name."""
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,
938 takes_options = [
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,
958 versionopts=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 "@"')
964 select_flags = 0
965 if authority:
966 select_flags |= dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
967 if cache:
968 select_flags |= dnsserver.DNS_RPC_VIEW_CACHE_DATA
969 if glue:
970 select_flags |= dnsserver.DNS_RPC_VIEW_GLUE_DATA
971 if root:
972 select_flags |= dnsserver.DNS_RPC_VIEW_ROOT_HINT_DATA
973 if additional:
974 select_flags |= dnsserver.DNS_RPC_VIEW_ADDITIONAL_DATA
975 if no_children:
976 select_flags |= dnsserver.DNS_RPC_VIEW_NO_CHILDREN
977 if only_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,
1012 versionopts=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):
1028 """Add a DNS record
1030 For each type data contents are as follows:
1031 A ipv4_address_string
1032 AAAA ipv6_address_string
1033 PTR fqdn_string
1034 CNAME fqdn_string
1035 NS fqdn_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,
1065 data)
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
1083 PTR fqdn_string
1084 CNAME fqdn_string
1085 NS fqdn_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,
1116 olddata)
1117 if not rec_match:
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,
1134 server,
1135 zone,
1136 name,
1137 add_rec_buf,
1138 del_rec_buf)
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
1148 PTR fqdn_string
1149 CNAME fqdn_string
1150 NS fqdn_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)
1178 if not rec_match:
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,
1186 server,
1187 zone,
1188 name,
1189 None,
1190 del_rec_buf)
1191 self.outf.write('Record deleted successfully\n')
1194 class cmd_dns(SuperCommand):
1195 """Domain Name Service (DNS) management."""
1197 subcommands = {}
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()