# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
+import logging
import samba.getopt as options
+from samba import WERRORError
+from samba import werror
from struct import pack
from socket import inet_ntoa
+from socket import inet_ntop
+from socket import AF_INET
+from socket import AF_INET6
import shlex
+from samba import remove_dc
+from samba.samdb import SamDB
+from samba.auth import system_session
+
from samba.netcmd import (
Command,
CommandError,
Option,
SuperCommand,
- )
+)
from samba.dcerpc import dnsp, dnsserver
+from samba.dnsserver import ARecord, AAAARecord, PTRRecord, CNameRecord, NSRecord, MXRecord, SOARecord, SRVRecord, TXTRecord
def dns_connect(server, lp, creds):
if server.lower() == 'localhost':
server = '127.0.0.1'
binding_str = "ncacn_ip_tcp:%s[sign]" % server
- dns_conn = dnsserver.dnsserver(binding_str, lp, creds)
+ try:
+ dns_conn = dnsserver.dnsserver(binding_str, lp, creds)
+ except RuntimeError as e:
+ raise CommandError('Connecting to DNS RPC server %s failed with %s' % (server, e))
+
return dns_conn
def boot_method_string(boot_method):
- enum_defs = [ 'DNS_BOOT_METHOD_UNINITIALIZED', 'DNS_BOOT_METHOD_FILE',
- 'DNS_BOOT_METHOD_REGISTRY', 'DNS_BOOT_METHOD_DIRECTORY' ]
+ enum_defs = ['DNS_BOOT_METHOD_UNINITIALIZED', 'DNS_BOOT_METHOD_FILE',
+ 'DNS_BOOT_METHOD_REGISTRY', 'DNS_BOOT_METHOD_DIRECTORY']
return enum_string(dnsserver, enum_defs, boot_method)
def name_check_flag_string(check_flag):
- enum_defs = [ 'DNS_ALLOW_RFC_NAMES_ONLY', 'DNS_ALLOW_NONRFC_NAMES',
- 'DNS_ALLOW_MULTIBYTE_NAMES', 'DNS_ALLOW_ALL_NAMES' ]
+ enum_defs = ['DNS_ALLOW_RFC_NAMES_ONLY', 'DNS_ALLOW_NONRFC_NAMES',
+ 'DNS_ALLOW_MULTIBYTE_NAMES', 'DNS_ALLOW_ALL_NAMES']
return enum_string(dnsserver, enum_defs, check_flag)
def zone_type_string(zone_type):
- enum_defs = [ 'DNS_ZONE_TYPE_CACHE', 'DNS_ZONE_TYPE_PRIMARY',
- 'DNS_ZONE_TYPE_SECONDARY', 'DNS_ZONE_TYPE_STUB',
- 'DNS_ZONE_TYPE_FORWARDER', 'DNS_ZONE_TYPE_SECONDARY_CACHE' ]
+ enum_defs = ['DNS_ZONE_TYPE_CACHE', 'DNS_ZONE_TYPE_PRIMARY',
+ 'DNS_ZONE_TYPE_SECONDARY', 'DNS_ZONE_TYPE_STUB',
+ 'DNS_ZONE_TYPE_FORWARDER', 'DNS_ZONE_TYPE_SECONDARY_CACHE']
return enum_string(dnsp, enum_defs, zone_type)
def zone_update_string(zone_update):
- enum_defs = [ 'DNS_ZONE_UPDATE_OFF', 'DNS_ZONE_UPDATE_SECURE',
- 'DNS_ZONE_UPDATE_SECURE' ]
+ enum_defs = ['DNS_ZONE_UPDATE_OFF', 'DNS_ZONE_UPDATE_UNSECURE',
+ 'DNS_ZONE_UPDATE_SECURE']
return enum_string(dnsp, enum_defs, zone_update)
def zone_secondary_security_string(security):
- enum_defs = [ 'DNS_ZONE_SECSECURE_NO_SECURITY', 'DNS_ZONE_SECSECURE_NS_ONLY',
- 'DNS_ZONE_SECSECURE_LIST_ONLY', 'DNS_ZONE_SECSECURE_NO_XFER' ]
+ enum_defs = ['DNS_ZONE_SECSECURE_NO_SECURITY', 'DNS_ZONE_SECSECURE_NS_ONLY',
+ 'DNS_ZONE_SECSECURE_LIST_ONLY', 'DNS_ZONE_SECSECURE_NO_XFER']
return enum_string(dnsserver, enum_defs, security)
def zone_notify_level_string(notify_level):
- enum_defs = [ 'DNS_ZONE_NOTIFY_OFF', 'DNS_ZONE_NOTIFY_ALL_SECONDARIES',
- 'DNS_ZONE_NOTIFY_LIST_ONLY' ]
+ enum_defs = ['DNS_ZONE_NOTIFY_OFF', 'DNS_ZONE_NOTIFY_ALL_SECONDARIES',
+ 'DNS_ZONE_NOTIFY_LIST_ONLY']
return enum_string(dnsserver, enum_defs, notify_level)
def dp_flags_string(dp_flags):
- bitmap_defs = [ 'DNS_DP_AUTOCREATED', 'DNS_DP_LEGACY', 'DNS_DP_DOMAIN_DEFAULT',
- 'DNS_DP_FOREST_DEFAULT', 'DNS_DP_ENLISTED', 'DNS_DP_DELETED' ]
+ bitmap_defs = ['DNS_DP_AUTOCREATED', 'DNS_DP_LEGACY', 'DNS_DP_DOMAIN_DEFAULT',
+ 'DNS_DP_FOREST_DEFAULT', 'DNS_DP_ENLISTED', 'DNS_DP_DELETED']
return bitmap_string(dnsserver, bitmap_defs, dp_flags)
def zone_flags_string(flags):
- bitmap_defs = [ 'DNS_RPC_ZONE_PAUSED', 'DNS_RPC_ZONE_SHUTDOWN',
+ bitmap_defs = ['DNS_RPC_ZONE_PAUSED', 'DNS_RPC_ZONE_SHUTDOWN',
'DNS_RPC_ZONE_REVERSE', 'DNS_RPC_ZONE_AUTOCREATED',
'DNS_RPC_ZONE_DSINTEGRATED', 'DNS_RPC_ZONE_AGING',
'DNS_RPC_ZONE_UPDATE_UNSECURE', 'DNS_RPC_ZONE_UPDATE_SECURE',
ret = []
if not array:
return ret
- for i in xrange(array.AddrCount):
- addr = '%s' % inet_ntoa(pack('i', array.AddrArray[i]))
+ for i in range(array.AddrCount):
+ addr = inet_ntop(AF_INET, pack('I', array.AddrArray[i]))
ret.append(addr)
return ret
ret = []
if not array:
return ret
- for i in xrange(array.AddrCount):
+ for i in range(array.AddrCount):
if array.AddrArray[i].MaxSa[0] == 0x02:
- addr = '%d.%d.%d.%d (%d)' % \
- tuple(array.AddrArray[i].MaxSa[4:8] + [array.AddrArray[i].MaxSa[3]])
+ x = "".join([chr(b) for b in array.AddrArray[i].MaxSa])[4:8]
+ addr = inet_ntop(AF_INET, x)
elif array.AddrArray[i].MaxSa[0] == 0x17:
- addr = '%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x (%d)' % \
- tuple(array.AddrArray[i].MaxSa[4:20] + [array.AddrArray[i].MaxSa[3]])
+ x = "".join([chr(b) for b in array.AddrArray[i].MaxSa])[8:24]
+ addr = inet_ntop(AF_INET6, x)
else:
addr = 'UNKNOWN'
ret.append(addr)
if typeid != dnsserver.DNSSRV_TYPEID_SERVER_INFO:
outf.write(' aipServerAddrs : %s\n' %
- ip4_array_string(serverinfo.aipServerAddrs))
+ ip4_array_string(serverinfo.aipServerAddrs))
outf.write(' aipListenAddrs : %s\n' %
- ip4_array_string(serverinfo.aipListenAddrs))
+ ip4_array_string(serverinfo.aipListenAddrs))
outf.write(' aipForwarders : %s\n' %
- ip4_array_string(serverinfo.aipForwarders))
+ ip4_array_string(serverinfo.aipForwarders))
else:
outf.write(' aipServerAddrs : %s\n' %
- dns_addr_array_string(serverinfo.aipServerAddrs))
+ dns_addr_array_string(serverinfo.aipServerAddrs))
outf.write(' aipListenAddrs : %s\n' %
- dns_addr_array_string(serverinfo.aipListenAddrs))
+ dns_addr_array_string(serverinfo.aipListenAddrs))
outf.write(' aipForwarders : %s\n' %
- dns_addr_array_string(serverinfo.aipForwarders))
+ dns_addr_array_string(serverinfo.aipForwarders))
outf.write(' dwLogLevel : %d\n' % serverinfo.dwLogLevel)
outf.write(' dwDebugLevel : %d\n' % serverinfo.dwDebugLevel)
outf.write(' pszDataFile : %s\n' % zoneinfo.pszDataFile)
if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
outf.write(' aipMasters : %s\n' %
- ip4_array_string(zoneinfo.aipMasters))
+ ip4_array_string(zoneinfo.aipMasters))
else:
outf.write(' aipMasters : %s\n' %
- dns_addr_array_string(zoneinfo.aipMasters))
+ dns_addr_array_string(zoneinfo.aipMasters))
outf.write(' fSecureSecondaries : %s\n' % zone_secondary_security_string(zoneinfo.fSecureSecondaries))
outf.write(' fNotifyLevel : %s\n' % zone_notify_level_string(zoneinfo.fNotifyLevel))
if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
outf.write(' aipSecondaries : %s\n' %
- ip4_array_string(zoneinfo.aipSecondaries))
+ ip4_array_string(zoneinfo.aipSecondaries))
outf.write(' aipNotify : %s\n' %
- ip4_array_string(zoneinfo.aipNotify))
+ ip4_array_string(zoneinfo.aipNotify))
else:
outf.write(' aipSecondaries : %s\n' %
- dns_addr_array_string(zoneinfo.aipSecondaries))
+ dns_addr_array_string(zoneinfo.aipSecondaries))
outf.write(' aipNotify : %s\n' %
- dns_addr_array_string(zoneinfo.aipNotify))
+ dns_addr_array_string(zoneinfo.aipNotify))
outf.write(' fUseWins : %s\n' % bool_string(zoneinfo.fUseWins))
outf.write(' fUseNbstat : %s\n' % bool_string(zoneinfo.fUseNbstat))
outf.write(' fAging : %s\n' % bool_string(zoneinfo.fAging))
outf.write(' dwAvailForScavengeTime : %d\n' % zoneinfo.dwAvailForScavengeTime)
if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
outf.write(' aipScavengeServers : %s\n' %
- ip4_array_string(zoneinfo.aipScavengeServers))
+ ip4_array_string(zoneinfo.aipScavengeServers))
else:
outf.write(' aipScavengeServers : %s\n' %
- dns_addr_array_string(zoneinfo.aipScavengeServers))
+ dns_addr_array_string(zoneinfo.aipScavengeServers))
if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO_W2K:
outf.write(' dwRpcStructureVersion : 0x%x\n' % zoneinfo.dwRpcStructureVersion)
outf.write(' fForwarderSlave : %d\n' % zoneinfo.fForwarderSlave)
if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
outf.write(' aipLocalMasters : %s\n' %
- ip4_array_string(zoneinfo.aipLocalMasters))
+ ip4_array_string(zoneinfo.aipLocalMasters))
else:
outf.write(' aipLocalMasters : %s\n' %
- dns_addr_array_string(zoneinfo.aipLocalMasters))
+ dns_addr_array_string(zoneinfo.aipLocalMasters))
outf.write(' dwDpFlags : %s\n' % dp_flags_string(zoneinfo.dwDpFlags))
outf.write(' pszDpFqdn : %s\n' % zoneinfo.pszDpFqdn)
outf.write(' pwszZoneDn : %s\n' % zoneinfo.pwszZoneDn)
print_dns_record(outf, dns_rec)
-#
-# Always create a copy of strings when creating DNS_RPC_RECORDs
-# to overcome the bug in pidl generated python bindings.
-#
-
-class ARecord(dnsserver.DNS_RPC_RECORD):
- def __init__(self, ip_addr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
- node_flag=0):
- super(ARecord, self).__init__()
- self.wType = dnsp.DNS_TYPE_A
- self.dwFlags = rank | node_flag
- self.dwSerial = serial
- self.dwTtlSeconds = ttl
- self._ip_addr = ip_addr[:]
- self.data = self._ip_addr
-
-
-class AAAARecord(dnsserver.DNS_RPC_RECORD):
-
- def __init__(self, ip6_addr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
- node_flag=0):
- super(AAAARecord, self).__init__()
- self.wType = dnsp.DNS_TYPE_AAAA
- self.dwFlags = rank | node_flag
- self.dwSerial = serial
- self.dwTtlSeconds = ttl
- self._ip6_addr = ip6_addr[:]
- self.data = self._ip6_addr
-
-
-class PTRRecord(dnsserver.DNS_RPC_RECORD):
-
- def __init__(self, ptr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
- node_flag=0):
- super(PTRRecord, self).__init__()
- self.wType = dnsp.DNS_TYPE_PTR
- self.dwFlags = rank | node_flag
- self.dwSerial = serial
- self.dwTtlSeconds = ttl
- self._ptr = ptr[:]
- ptr_name = dnsserver.DNS_RPC_NAME()
- ptr_name.str = self._ptr
- ptr_name.len = len(ptr)
- self.data = ptr_name
-
-
-class CNameRecord(dnsserver.DNS_RPC_RECORD):
-
- def __init__(self, cname, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
- node_flag=0):
- super(CNameRecord, self).__init__()
- self.wType = dnsp.DNS_TYPE_CNAME
- self.dwFlags = rank | node_flag
- self.dwSerial = serial
- self.dwTtlSeconds = ttl
- self._cname = cname[:]
- cname_name = dnsserver.DNS_RPC_NAME()
- cname_name.str = self._cname
- cname_name.len = len(cname)
- self.data = cname_name
-
-
-class NSRecord(dnsserver.DNS_RPC_RECORD):
-
- def __init__(self, dns_server, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
- node_flag=0):
- super(NSRecord, self).__init__()
- self.wType = dnsp.DNS_TYPE_NS
- self.dwFlags = rank | node_flag
- self.dwSerial = serial
- self.dwTtlSeconds = ttl
- self._dns_server = dns_server[:]
- ns = dnsserver.DNS_RPC_NAME()
- ns.str = self._dns_server
- ns.len = len(dns_server)
- self.data = ns
-
-
-class MXRecord(dnsserver.DNS_RPC_RECORD):
-
- def __init__(self, mail_server, preference, serial=1, ttl=900,
- rank=dnsp.DNS_RANK_ZONE, node_flag=0):
- super(MXRecord, self).__init__()
- self.wType = dnsp.DNS_TYPE_MX
- self.dwFlags = rank | node_flag
- self.dwSerial = serial
- self.dwTtlSeconds = ttl
- self._mail_server = mail_server[:]
- mx = dnsserver.DNS_RPC_RECORD_NAME_PREFERENCE()
- mx.wPreference = preference
- mx.nameExchange.str = self._mail_server
- mx.nameExchange.len = len(mail_server)
- self.data = mx
-
-
-class SOARecord(dnsserver.DNS_RPC_RECORD):
-
- def __init__(self, mname, rname, serial=1, refresh=900, retry=600,
- expire=86400, minimum=3600, ttl=3600, rank=dnsp.DNS_RANK_ZONE,
- node_flag=dnsp.DNS_RPC_FLAG_AUTH_ZONE_ROOT):
- super(SOARecord, self).__init__()
- self.wType = dnsp.DNS_TYPE_SOA
- self.dwFlags = rank | node_flag
- self.dwSerial = serial
- self.dwTtlSeconds = ttl
- self._mname = mname[:]
- self._rname = rname[:]
- soa = dnsserver.DNS_RPC_RECORD_SOA()
- soa.dwSerialNo = serial
- soa.dwRefresh = refresh
- soa.dwRetry = retry
- soa.dwExpire = expire
- soa.dwMinimumTtl = minimum
- soa.NamePrimaryServer.str = self._mname
- soa.NamePrimaryServer.len = len(mname)
- soa.ZoneAdministratorEmail.str = self._rname
- soa.ZoneAdministratorEmail.len = len(rname)
- self.data = soa
-
-
-class SRVRecord(dnsserver.DNS_RPC_RECORD):
-
- def __init__(self, target, port, priority=0, weight=100, serial=1, ttl=900,
- rank=dnsp.DNS_RANK_ZONE, node_flag=0):
- super(SRVRecord, self).__init__()
- self.wType = dnsp.DNS_TYPE_SRV
- self.dwFlags = rank | node_flag
- self.dwSerial = serial
- self.dwTtlSeconds = ttl
- self._target = target[:]
- srv = dnsserver.DNS_RPC_RECORD_SRV()
- srv.wPriority = priority
- srv.wWeight = weight
- srv.wPort = port
- srv.nameTarget.str = self._target
- srv.nameTarget.len = len(target)
- self.data = srv
-
-
-class TXTRecord(dnsserver.DNS_RPC_RECORD):
-
- def __init__(self, slist, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
- node_flag=0):
- super(TXTRecord, self).__init__()
- self.wType = dnsp.DNS_TYPE_TXT
- self.dwFlags = rank | node_flag
- self.dwSerial = serial
- self.dwTtlSeconds = ttl
- self._slist = []
- for s in slist:
- self._slist.append(s[:])
- names = []
- for s in self._slist:
- name = dnsserver.DNS_RPC_NAME()
- name.str = s
- name.len = len(s)
- names.append(name)
- txt = dnsserver.DNS_RPC_RECORD_STRING()
- txt.count = len(slist)
- txt.str = names
- self.data = txt
# Convert data into a dns record
buflen, res = dns_conn.DnssrvEnumRecords2(
dnsserver.DNS_CLIENT_VERSION_LONGHORN, 0, server, zone, name, None,
record_type, select_flags, None, None)
- except RuntimeError, e:
- return None
+ except WERRORError as e:
+ if e.args[0] == werror.WERR_DNS_ERROR_NAME_DOES_NOT_EXIST:
+ # Either the zone doesn't exist, or there were no records.
+ # We can't differentiate the two.
+ return None
+ raise e
if not res or res.count == 0:
return None
- rec_match = None
for rec in res.rec[0].records:
if rec.wType != record_type:
continue
elif record_type == dnsp.DNS_TYPE_TXT:
if rec.data.count == urec.data.count:
found = True
- for i in xrange(rec.data.count):
+ for i in range(rec.data.count):
found = found and \
(rec.data.str[i].str == urec.data.str[i].str)
if found:
- rec_match = rec
- break
+ return rec
- return rec_match
+ return None
class cmd_serverinfo(Command):
synopsis = '%prog <server> [options]'
- takes_args = [ 'server' ]
+ takes_args = ['server']
takes_optiongroups = {
"sambaopts": options.SambaOptions,
takes_options = [
Option('--client-version', help='Client Version',
- default='longhorn', metavar='w2k|dotnet|longhorn',
- choices=['w2k','dotnet','longhorn'], dest='cli_ver'),
+ default='longhorn', metavar='w2k|dotnet|longhorn',
+ choices=['w2k', 'dotnet', 'longhorn'], dest='cli_ver'),
]
def run(self, server, cli_ver, sambaopts=None, credopts=None,
synopsis = '%prog <server> <zone> [options]'
- takes_args = [ 'server', 'zone' ]
+ takes_args = ['server', 'zone']
takes_optiongroups = {
"sambaopts": options.SambaOptions,
takes_options = [
Option('--client-version', help='Client Version',
- default='longhorn', metavar='w2k|dotnet|longhorn',
- choices=['w2k','dotnet','longhorn'], dest='cli_ver'),
+ default='longhorn', metavar='w2k|dotnet|longhorn',
+ choices=['w2k', 'dotnet', 'longhorn'], dest='cli_ver'),
]
def run(self, server, zone, cli_ver, sambaopts=None, credopts=None,
synopsis = '%prog <server> [options]'
- takes_args = [ 'server' ]
+ takes_args = ['server']
takes_optiongroups = {
"sambaopts": options.SambaOptions,
takes_options = [
Option('--client-version', help='Client Version',
- default='longhorn', metavar='w2k|dotnet|longhorn',
- choices=['w2k','dotnet','longhorn'], dest='cli_ver'),
+ default='longhorn', metavar='w2k|dotnet|longhorn',
+ choices=['w2k', 'dotnet', 'longhorn'], dest='cli_ver'),
Option('--primary', help='List primary zones (default)',
- action='store_true', dest='primary'),
+ action='store_true', dest='primary'),
Option('--secondary', help='List secondary zones',
- action='store_true', dest='secondary'),
+ action='store_true', dest='secondary'),
Option('--cache', help='List cached zones',
- action='store_true', dest='cache'),
+ action='store_true', dest='cache'),
Option('--auto', help='List automatically created zones',
- action='store_true', dest='auto'),
+ action='store_true', dest='auto'),
Option('--forward', help='List forward zones',
- action='store_true', dest='forward'),
+ action='store_true', dest='forward'),
Option('--reverse', help='List reverse zones',
- action='store_true', dest='reverse'),
+ action='store_true', dest='reverse'),
Option('--ds', help='List directory integrated zones',
- action='store_true', dest='ds'),
+ action='store_true', dest='ds'),
Option('--non-ds', help='List non-directory zones',
- action='store_true', dest='nonds')
+ action='store_true', dest='nonds')
]
def run(self, server, cli_ver, primary=False, secondary=False, cache=False,
- auto=False, forward=False, reverse=False, ds=False, nonds=False,
- sambaopts=None, credopts=None, versionopts=None):
+ auto=False, forward=False, reverse=False, ds=False, nonds=False,
+ sambaopts=None, credopts=None, versionopts=None):
request_filter = 0
if primary:
client_version = dns_client_version(cli_ver)
typeid, res = dns_conn.DnssrvComplexOperation2(client_version,
- 0, server, None,
- 'EnumZones',
- dnsserver.DNSSRV_TYPEID_DWORD,
- request_filter)
+ 0, server, None,
+ 'EnumZones',
+ dnsserver.DNSSRV_TYPEID_DWORD,
+ request_filter)
if client_version == dnsserver.DNS_CLIENT_VERSION_W2K:
typeid = dnsserver.DNSSRV_TYPEID_ZONE_W2K
synopsis = '%prog <server> <zone> [options]'
- takes_args = [ 'server', 'zone' ]
+ takes_args = ['server', 'zone']
takes_optiongroups = {
"sambaopts": options.SambaOptions,
takes_options = [
Option('--client-version', help='Client Version',
- default='longhorn', metavar='w2k|dotnet|longhorn',
- choices=['w2k','dotnet','longhorn'], dest='cli_ver')
+ default='longhorn', metavar='w2k|dotnet|longhorn',
+ choices=['w2k', 'dotnet', 'longhorn'], dest='cli_ver')
]
def run(self, server, zone, cli_ver, sambaopts=None, credopts=None,
zone_create_info = dnsserver.DNS_RPC_ZONE_CREATE_INFO_W2K()
zone_create_info.pszZoneName = zone
zone_create_info.dwZoneType = dnsp.DNS_ZONE_TYPE_PRIMARY
- zone_create_info.fAllowUpdate = dnsp.DNS_ZONE_UPDATE_SECURE
zone_create_info.fAging = 0
+ zone_create_info.fDsIntegrated = 1
+ zone_create_info.fLoadExisting = 1
elif client_version == dnsserver.DNS_CLIENT_VERSION_DOTNET:
typeid = dnsserver.DNSSRV_TYPEID_ZONE_CREATE_DOTNET
zone_create_info = dnsserver.DNS_RPC_ZONE_CREATE_INFO_DOTNET()
zone_create_info.pszZoneName = zone
zone_create_info.dwZoneType = dnsp.DNS_ZONE_TYPE_PRIMARY
- zone_create_info.fAllowUpdate = dnsp.DNS_ZONE_UPDATE_SECURE
zone_create_info.fAging = 0
+ zone_create_info.fDsIntegrated = 1
+ zone_create_info.fLoadExisting = 1
zone_create_info.dwDpFlags = dnsserver.DNS_DP_DOMAIN_DEFAULT
else:
typeid = dnsserver.DNSSRV_TYPEID_ZONE_CREATE
zone_create_info = dnsserver.DNS_RPC_ZONE_CREATE_INFO_LONGHORN()
zone_create_info.pszZoneName = zone
zone_create_info.dwZoneType = dnsp.DNS_ZONE_TYPE_PRIMARY
- zone_create_info.fAllowUpdate = dnsp.DNS_ZONE_UPDATE_SECURE
zone_create_info.fAging = 0
+ zone_create_info.fDsIntegrated = 1
+ zone_create_info.fLoadExisting = 1
zone_create_info.dwDpFlags = dnsserver.DNS_DP_DOMAIN_DEFAULT
res = dns_conn.DnssrvOperation2(client_version, 0, server, None,
0, 'ZoneCreate', typeid,
zone_create_info)
+
+ typeid = dnsserver.DNSSRV_TYPEID_NAME_AND_PARAM
+ name_and_param = dnsserver.DNS_RPC_NAME_AND_PARAM()
+ name_and_param.pszNodeName = 'AllowUpdate'
+ name_and_param.dwParam = dnsp.DNS_ZONE_UPDATE_SECURE
+
+ try:
+ res = dns_conn.DnssrvOperation2(client_version, 0, server, zone,
+ 0, 'ResetDwordProperty', typeid,
+ name_and_param)
+ except WERRORError as e:
+ if e.args[0] == werror.WERR_DNS_ERROR_ZONE_ALREADY_EXISTS:
+ self.outf.write('Zone already exists.')
+ raise e
+
self.outf.write('Zone %s created successfully\n' % zone)
synopsis = '%prog <server> <zone> [options]'
- takes_args = [ 'server', 'zone' ]
+ takes_args = ['server', 'zone']
takes_optiongroups = {
"sambaopts": options.SambaOptions,
dns_conn = dns_connect(server, self.lp, self.creds)
zone = zone.lower()
- res = dns_conn.DnssrvOperation2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
- 0, server, zone, 0, 'DeleteZoneFromDs',
- dnsserver.DNSSRV_TYPEID_NULL,
- None)
- self.outf.write('Zone %s delete successfully\n' % zone)
+ try:
+ res = dns_conn.DnssrvOperation2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, server, zone, 0, 'DeleteZoneFromDs',
+ dnsserver.DNSSRV_TYPEID_NULL,
+ None)
+ except WERRORError as e:
+ if e.args[0] == werror.WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST:
+ self.outf.write('Zone does not exist and so could not be deleted.')
+ raise e
+
+ self.outf.write('Zone %s deleted successfully\n' % zone)
class cmd_query(Command):
synopsis = '%prog <server> <zone> <name> <A|AAAA|CNAME|MX|NS|SOA|SRV|TXT|ALL> [options]'
- takes_args = [ 'server', 'zone', 'name', 'rtype' ]
+ takes_args = ['server', 'zone', 'name', 'rtype']
takes_optiongroups = {
"sambaopts": options.SambaOptions,
takes_options = [
Option('--authority', help='Search authoritative records (default)',
- action='store_true', dest='authority'),
+ action='store_true', dest='authority'),
Option('--cache', help='Search cached records',
- action='store_true', dest='cache'),
+ action='store_true', dest='cache'),
Option('--glue', help='Search glue records',
- action='store_true', dest='glue'),
+ action='store_true', dest='glue'),
Option('--root', help='Search root hints',
- action='store_true', dest='root'),
+ action='store_true', dest='root'),
Option('--additional', help='List additional records',
- action='store_true', dest='additional'),
+ action='store_true', dest='additional'),
Option('--no-children', help='Do not list children',
- action='store_true', dest='no_children'),
+ action='store_true', dest='no_children'),
Option('--only-children', help='List only children',
- action='store_true', dest='only_children')
+ action='store_true', dest='only_children')
]
def run(self, server, zone, name, rtype, authority=False, cache=False,
versionopts=None):
record_type = dns_type_flag(rtype)
+ if name.find('*') != -1:
+ self.outf.write('use "@" to dump entire domain, looking up %s\n' %
+ name)
+
select_flags = 0
if authority:
select_flags |= dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
self.creds = credopts.get_credentials(self.lp)
dns_conn = dns_connect(server, self.lp, self.creds)
- buflen, res = dns_conn.DnssrvEnumRecords2(
+ try:
+ buflen, res = dns_conn.DnssrvEnumRecords2(
dnsserver.DNS_CLIENT_VERSION_LONGHORN, 0, server, zone, name,
None, record_type, select_flags, None, None)
+ except WERRORError as e:
+ if e.args[0] == werror.WERR_DNS_ERROR_NAME_DOES_NOT_EXIST:
+ self.outf.write('Record or zone does not exist.')
+ raise e
+
print_dnsrecords(self.outf, res)
synopsis = '%prog <server> [<name>] [options]'
- takes_args = [ 'server', 'name?' ]
+ takes_args = ['server', 'name?']
takes_optiongroups = {
"sambaopts": options.SambaOptions,
synopsis = '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SRV|TXT> <data>'
- takes_args = [ 'server', 'zone', 'name', 'rtype', 'data' ]
+ takes_args = ['server', 'zone', 'name', 'rtype', 'data']
takes_optiongroups = {
"sambaopts": options.SambaOptions,
def run(self, server, zone, name, rtype, data, sambaopts=None,
credopts=None, versionopts=None):
- if rtype.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SRV','TXT'):
+ if rtype.upper() not in ('A', 'AAAA', 'PTR', 'CNAME', 'NS', 'MX', 'SRV', 'TXT'):
raise CommandError('Adding record of type %s is not supported' % rtype)
record_type = dns_type_flag(rtype)
self.creds = credopts.get_credentials(self.lp)
dns_conn = dns_connect(server, self.lp, self.creds)
- rec_match = dns_record_match(dns_conn, server, zone, name, record_type,
- data)
- if rec_match is not None:
- raise CommandError('Record already exists')
-
add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
add_rec_buf.rec = rec
- dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
- 0, server, zone, name, add_rec_buf, None)
+ try:
+ dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0, server, zone, name, add_rec_buf, None)
+ except WERRORError as e:
+ if e.args[0] == werror.WERR_DNS_ERROR_NAME_DOES_NOT_EXIST:
+ self.outf.write('Zone does not exist; record could not be added.\n')
+ raise e
+
self.outf.write('Record added successfully\n')
synopsis = '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SOA|SRV|TXT> <olddata> <newdata>'
- takes_args = [ 'server', 'zone', 'name', 'rtype', 'olddata', 'newdata' ]
+ takes_args = ['server', 'zone', 'name', 'rtype', 'olddata', 'newdata']
takes_optiongroups = {
"sambaopts": options.SambaOptions,
}
def run(self, server, zone, name, rtype, olddata, newdata,
- sambaopts=None, credopts=None, versionopts=None):
+ sambaopts=None, credopts=None, versionopts=None):
- if rtype.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SOA','SRV','TXT'):
+ if rtype.upper() not in ('A', 'AAAA', 'PTR', 'CNAME', 'NS', 'MX', 'SOA', 'SRV', 'TXT'):
raise CommandError('Updating record of type %s is not supported' % rtype)
record_type = dns_type_flag(rtype)
dns_conn = dns_connect(server, self.lp, self.creds)
rec_match = dns_record_match(dns_conn, server, zone, name, record_type,
- olddata)
+ olddata)
if not rec_match:
- raise CommandError('Record does not exist')
+ raise CommandError('Record or zone does not exist.')
# Copy properties from existing record to new record
rec.dwFlags = rec_match.dwFlags
del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
del_rec_buf.rec = rec_match
- dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
- 0,
- server,
- zone,
- name,
- add_rec_buf,
- del_rec_buf)
+ try:
+ dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0,
+ server,
+ zone,
+ name,
+ add_rec_buf,
+ del_rec_buf)
+ except WERRORError as e:
+ if e.args[0] == werror.WERR_DNS_ERROR_NAME_DOES_NOT_EXIST:
+ self.outf.write('Zone does not exist; record could not be updated.\n')
+ raise e
+
self.outf.write('Record updated successfully\n')
synopsis = '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SRV|TXT> <data>'
- takes_args = [ 'server', 'zone', 'name', 'rtype', 'data' ]
+ takes_args = ['server', 'zone', 'name', 'rtype', 'data']
takes_optiongroups = {
"sambaopts": options.SambaOptions,
def run(self, server, zone, name, rtype, data, sambaopts=None, credopts=None, versionopts=None):
- if rtype.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SRV','TXT'):
+ if rtype.upper() not in ('A', 'AAAA', 'PTR', 'CNAME', 'NS', 'MX', 'SRV', 'TXT'):
raise CommandError('Deleting record of type %s is not supported' % rtype)
record_type = dns_type_flag(rtype)
+ rec = data_to_dns_record(record_type, data)
self.lp = sambaopts.get_loadparm()
self.creds = credopts.get_credentials(self.lp)
dns_conn = dns_connect(server, self.lp, self.creds)
- rec_match = dns_record_match(dns_conn, server, zone, name, record_type, data)
- if not rec_match:
- raise CommandError('Record does not exist')
-
del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
- del_rec_buf.rec = rec_match
+ del_rec_buf.rec = rec
+
+ try:
+ dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
+ 0,
+ server,
+ zone,
+ name,
+ None,
+ del_rec_buf)
+ except WERRORError as e:
+ if e.args[0] == werror.WERR_DNS_ERROR_NAME_DOES_NOT_EXIST:
+ self.outf.write('Zone does not exist; record could not be deleted.\n')
+ raise e
- dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
- 0,
- server,
- zone,
- name,
- None,
- del_rec_buf)
self.outf.write('Record deleted successfully\n')
+class cmd_cleanup_record(Command):
+ """Cleanup DNS records for a DNS host.
+
+ example:
+
+ samba-tool dns cleanup dc1 dc1.samdom.test.site -U USER%PASSWORD
+
+ NOTE: This command in many cases will only mark the `dNSTombstoned` attr
+ as `TRUE` on the DNS records. Querying will no longer return results but
+ there may still be some placeholder entries in the database.
+ """
+
+ synopsis = '%prog <server> <dnshostname>'
+
+ takes_args = ['server', 'dnshostname']
+
+ takes_optiongroups = {
+ "sambaopts": options.SambaOptions,
+ "versionopts": options.VersionOptions,
+ "credopts": options.CredentialsOptions,
+ }
+
+ takes_options = [
+ Option("-v", "--verbose", help="Be verbose", action="store_true"),
+ Option("-q", "--quiet", help="Be quiet", action="store_true"),
+ ]
+
+ def run(self, server, dnshostname, sambaopts=None, credopts=None,
+ versionopts=None, verbose=False, quiet=False):
+ lp = sambaopts.get_loadparm()
+ creds = credopts.get_credentials(lp)
+
+ logger = self.get_logger()
+ if verbose:
+ logger.setLevel(logging.DEBUG)
+ elif quiet:
+ logger.setLevel(logging.WARNING)
+ else:
+ logger.setLevel(logging.INFO)
+
+ samdb = SamDB(url="ldap://%s" % server,
+ session_info=system_session(),
+ credentials=creds, lp=lp)
+
+ remove_dc.remove_dns_references(samdb, logger, dnshostname,
+ ignore_no_name=True)
+
+
class cmd_dns(SuperCommand):
"""Domain Name Service (DNS) management."""
subcommands['add'] = cmd_add_record()
subcommands['update'] = cmd_update_record()
subcommands['delete'] = cmd_delete_record()
+ subcommands['cleanup'] = cmd_cleanup_record()