2011-10-17 06:15:40 +04:00
# DNS management tool
#
2012-02-16 03:17:25 +04:00
# Copyright (C) Amitay Isaacs 2011-2012
2011-10-17 06:15:40 +04:00
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
2018-01-12 04:14:00 +03:00
import logging
2011-10-17 06:15:40 +04:00
import samba . getopt as options
2016-11-25 06:29:31 +03:00
from samba import WERRORError
2017-02-13 01:12:54 +03:00
from samba import werror
2011-10-17 06:15:40 +04:00
from struct import pack
from socket import inet_ntoa
2014-11-21 05:55:25 +03:00
from socket import inet_ntop
from socket import AF_INET
from socket import AF_INET6
2012-02-28 08:14:49 +04:00
import shlex
2019-05-24 00:58:12 +03:00
import struct
2011-10-17 06:15:40 +04:00
2018-01-12 04:14:00 +03:00
from samba import remove_dc
from samba . samdb import SamDB
from samba . auth import system_session
2011-10-17 06:15:40 +04:00
from samba . netcmd import (
Command ,
CommandError ,
Option ,
SuperCommand ,
2018-07-30 09:14:37 +03:00
)
2011-10-17 06:15:40 +04:00
from samba . dcerpc import dnsp , dnsserver
2021-03-26 10:41:29 +03:00
from samba . dnsserver import record_from_string , DNSParseError
2011-10-17 06:15:40 +04:00
2018-07-30 09:20:39 +03:00
2011-10-17 06:15:40 +04:00
def dns_connect ( server , lp , creds ) :
2012-11-14 14:32:06 +04:00
if server . lower ( ) == ' localhost ' :
server = ' 127.0.0.1 '
2011-10-17 06:15:40 +04:00
binding_str = " ncacn_ip_tcp: %s [sign] " % server
2015-08-07 07:27:23 +03:00
try :
dns_conn = dnsserver . dnsserver ( binding_str , lp , creds )
2018-02-14 00:07:23 +03:00
except RuntimeError as e :
2015-08-07 07:27:23 +03:00
raise CommandError ( ' Connecting to DNS RPC server %s failed with %s ' % ( server , e ) )
2011-10-17 06:15:40 +04:00
return dns_conn
2012-09-16 16:18:39 +04:00
2011-10-17 06:15:40 +04:00
def bool_string ( flag ) :
if flag == 0 :
ret = ' FALSE '
elif flag == 1 :
ret = ' TRUE '
else :
ret = ' UNKNOWN (0x %x ) ' % flag
return ret
2012-09-16 16:18:39 +04:00
2011-10-17 06:15:40 +04:00
def enum_string ( module , enum_defs , value ) :
ret = None
for e in enum_defs :
if value == getattr ( module , e ) :
ret = e
break
if not ret :
ret = ' UNKNOWN (0x %x ) ' % value
return ret
2012-09-16 16:18:39 +04:00
2011-10-17 06:15:40 +04:00
def bitmap_string ( module , bitmap_defs , value ) :
ret = ' '
for b in bitmap_defs :
if value & getattr ( module , b ) :
ret + = ' %s ' % b
if not ret :
ret = ' NONE '
return ret
2012-09-16 16:18:39 +04:00
2011-10-17 06:15:40 +04:00
def boot_method_string ( boot_method ) :
2018-07-30 09:16:43 +03:00
enum_defs = [ ' DNS_BOOT_METHOD_UNINITIALIZED ' , ' DNS_BOOT_METHOD_FILE ' ,
2018-09-03 16:05:48 +03:00
' DNS_BOOT_METHOD_REGISTRY ' , ' DNS_BOOT_METHOD_DIRECTORY ' ]
2011-10-17 06:15:40 +04:00
return enum_string ( dnsserver , enum_defs , boot_method )
2012-09-16 16:18:39 +04:00
2011-10-17 06:15:40 +04:00
def name_check_flag_string ( check_flag ) :
2018-07-30 09:16:43 +03:00
enum_defs = [ ' DNS_ALLOW_RFC_NAMES_ONLY ' , ' DNS_ALLOW_NONRFC_NAMES ' ,
2018-09-03 16:05:48 +03:00
' DNS_ALLOW_MULTIBYTE_NAMES ' , ' DNS_ALLOW_ALL_NAMES ' ]
2011-10-17 06:15:40 +04:00
return enum_string ( dnsserver , enum_defs , check_flag )
2012-09-16 16:18:39 +04:00
2011-10-17 06:15:40 +04:00
def zone_type_string ( zone_type ) :
2018-07-30 09:16:43 +03:00
enum_defs = [ ' DNS_ZONE_TYPE_CACHE ' , ' DNS_ZONE_TYPE_PRIMARY ' ,
2018-09-03 16:05:48 +03:00
' DNS_ZONE_TYPE_SECONDARY ' , ' DNS_ZONE_TYPE_STUB ' ,
' DNS_ZONE_TYPE_FORWARDER ' , ' DNS_ZONE_TYPE_SECONDARY_CACHE ' ]
2011-10-17 06:15:40 +04:00
return enum_string ( dnsp , enum_defs , zone_type )
2012-09-16 16:18:39 +04:00
2011-10-17 06:15:40 +04:00
def zone_update_string ( zone_update ) :
2018-07-30 09:16:43 +03:00
enum_defs = [ ' DNS_ZONE_UPDATE_OFF ' , ' DNS_ZONE_UPDATE_UNSECURE ' ,
2018-09-03 16:05:48 +03:00
' DNS_ZONE_UPDATE_SECURE ' ]
2011-10-17 06:15:40 +04:00
return enum_string ( dnsp , enum_defs , zone_update )
2012-09-16 16:18:39 +04:00
2011-10-17 06:15:40 +04:00
def zone_secondary_security_string ( security ) :
2018-07-30 09:16:43 +03:00
enum_defs = [ ' DNS_ZONE_SECSECURE_NO_SECURITY ' , ' DNS_ZONE_SECSECURE_NS_ONLY ' ,
2018-09-03 16:05:48 +03:00
' DNS_ZONE_SECSECURE_LIST_ONLY ' , ' DNS_ZONE_SECSECURE_NO_XFER ' ]
2011-10-17 06:15:40 +04:00
return enum_string ( dnsserver , enum_defs , security )
2012-09-16 16:18:39 +04:00
2011-10-17 06:15:40 +04:00
def zone_notify_level_string ( notify_level ) :
2018-07-30 09:16:43 +03:00
enum_defs = [ ' DNS_ZONE_NOTIFY_OFF ' , ' DNS_ZONE_NOTIFY_ALL_SECONDARIES ' ,
2018-09-03 16:05:48 +03:00
' DNS_ZONE_NOTIFY_LIST_ONLY ' ]
2011-10-17 06:15:40 +04:00
return enum_string ( dnsserver , enum_defs , notify_level )
2012-09-16 16:18:39 +04:00
2011-10-17 06:15:40 +04:00
def dp_flags_string ( dp_flags ) :
2018-07-30 09:16:43 +03:00
bitmap_defs = [ ' DNS_DP_AUTOCREATED ' , ' DNS_DP_LEGACY ' , ' DNS_DP_DOMAIN_DEFAULT ' ,
2018-09-03 16:05:48 +03:00
' DNS_DP_FOREST_DEFAULT ' , ' DNS_DP_ENLISTED ' , ' DNS_DP_DELETED ' ]
2011-10-17 06:15:40 +04:00
return bitmap_string ( dnsserver , bitmap_defs , dp_flags )
2012-09-16 16:18:39 +04:00
2011-10-17 06:15:40 +04:00
def zone_flags_string ( flags ) :
2018-07-30 09:16:43 +03:00
bitmap_defs = [ ' DNS_RPC_ZONE_PAUSED ' , ' DNS_RPC_ZONE_SHUTDOWN ' ,
2018-09-03 16:05:48 +03:00
' 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 ' ,
' DNS_RPC_ZONE_READONLY ' ]
2011-10-17 06:15:40 +04:00
return bitmap_string ( dnsserver , bitmap_defs , flags )
2012-09-16 16:18:39 +04:00
2011-10-17 06:15:40 +04:00
def ip4_array_string ( array ) :
ret = [ ]
if not array :
return ret
2018-05-04 14:19:57 +03:00
for i in range ( array . AddrCount ) :
2014-11-21 05:55:25 +03:00
addr = inet_ntop ( AF_INET , pack ( ' I ' , array . AddrArray [ i ] ) )
2011-10-17 06:15:40 +04:00
ret . append ( addr )
return ret
2012-09-16 16:18:39 +04:00
2011-10-17 06:15:40 +04:00
def dns_addr_array_string ( array ) :
ret = [ ]
if not array :
return ret
2018-05-04 14:19:57 +03:00
for i in range ( array . AddrCount ) :
2011-10-17 06:15:40 +04:00
if array . AddrArray [ i ] . MaxSa [ 0 ] == 0x02 :
2019-05-24 00:58:12 +03:00
x = struct . pack ( ' 4B ' , * array . AddrArray [ i ] . MaxSa [ 4 : 8 ] )
2014-11-21 05:55:25 +03:00
addr = inet_ntop ( AF_INET , x )
2011-10-17 06:15:40 +04:00
elif array . AddrArray [ i ] . MaxSa [ 0 ] == 0x17 :
2019-05-24 00:58:12 +03:00
x = struct . pack ( ' 16B ' , * array . AddrArray [ i ] . MaxSa [ 8 : 24 ] )
2014-11-21 05:55:25 +03:00
addr = inet_ntop ( AF_INET6 , x )
2011-10-17 06:15:40 +04:00
else :
addr = ' UNKNOWN '
ret . append ( addr )
return ret
2012-09-16 16:18:39 +04:00
2011-10-17 06:15:40 +04:00
def dns_type_flag ( rec_type ) :
rtype = rec_type . upper ( )
if rtype == ' A ' :
record_type = dnsp . DNS_TYPE_A
2011-10-21 04:27:28 +04:00
elif rtype == ' AAAA ' :
record_type = dnsp . DNS_TYPE_AAAA
2011-12-14 08:54:31 +04:00
elif rtype == ' PTR ' :
record_type = dnsp . DNS_TYPE_PTR
2011-10-17 06:15:40 +04:00
elif rtype == ' NS ' :
record_type = dnsp . DNS_TYPE_NS
elif rtype == ' CNAME ' :
record_type = dnsp . DNS_TYPE_CNAME
elif rtype == ' SOA ' :
record_type = dnsp . DNS_TYPE_SOA
elif rtype == ' MX ' :
record_type = dnsp . DNS_TYPE_MX
elif rtype == ' SRV ' :
record_type = dnsp . DNS_TYPE_SRV
2012-02-28 08:14:49 +04:00
elif rtype == ' TXT ' :
record_type = dnsp . DNS_TYPE_TXT
2011-10-17 06:15:40 +04:00
elif rtype == ' ALL ' :
record_type = dnsp . DNS_TYPE_ALL
else :
raise CommandError ( ' Unknown type of DNS record %s ' % rec_type )
return record_type
2012-09-16 16:18:39 +04:00
2011-10-17 06:15:40 +04:00
def dns_client_version ( cli_version ) :
version = cli_version . upper ( )
if version == ' W2K ' :
client_version = dnsserver . DNS_CLIENT_VERSION_W2K
elif version == ' DOTNET ' :
client_version = dnsserver . DNS_CLIENT_VERSION_DOTNET
elif version == ' LONGHORN ' :
client_version = dnsserver . DNS_CLIENT_VERSION_LONGHORN
else :
raise CommandError ( ' Unknown client version %s ' % cli_version )
return client_version
2012-09-16 16:18:39 +04:00
2011-10-17 06:15:40 +04:00
def print_serverinfo ( outf , typeid , serverinfo ) :
outf . write ( ' dwVersion : 0x %x \n ' % serverinfo . dwVersion )
outf . write ( ' fBootMethod : %s \n ' % boot_method_string ( serverinfo . fBootMethod ) )
outf . write ( ' fAdminConfigured : %s \n ' % bool_string ( serverinfo . fAdminConfigured ) )
outf . write ( ' fAllowUpdate : %s \n ' % bool_string ( serverinfo . fAllowUpdate ) )
outf . write ( ' fDsAvailable : %s \n ' % bool_string ( serverinfo . fDsAvailable ) )
outf . write ( ' pszServerName : %s \n ' % serverinfo . pszServerName )
outf . write ( ' pszDsContainer : %s \n ' % serverinfo . pszDsContainer )
if typeid != dnsserver . DNSSRV_TYPEID_SERVER_INFO :
outf . write ( ' aipServerAddrs : %s \n ' %
2018-07-30 09:15:34 +03:00
ip4_array_string ( serverinfo . aipServerAddrs ) )
2011-10-17 06:15:40 +04:00
outf . write ( ' aipListenAddrs : %s \n ' %
2018-07-30 09:15:34 +03:00
ip4_array_string ( serverinfo . aipListenAddrs ) )
2011-10-17 06:15:40 +04:00
outf . write ( ' aipForwarders : %s \n ' %
2018-07-30 09:15:34 +03:00
ip4_array_string ( serverinfo . aipForwarders ) )
2011-10-17 06:15:40 +04:00
else :
outf . write ( ' aipServerAddrs : %s \n ' %
2018-07-30 09:15:34 +03:00
dns_addr_array_string ( serverinfo . aipServerAddrs ) )
2011-10-17 06:15:40 +04:00
outf . write ( ' aipListenAddrs : %s \n ' %
2018-07-30 09:15:34 +03:00
dns_addr_array_string ( serverinfo . aipListenAddrs ) )
2011-10-17 06:15:40 +04:00
outf . write ( ' aipForwarders : %s \n ' %
2018-07-30 09:15:34 +03:00
dns_addr_array_string ( serverinfo . aipForwarders ) )
2011-10-17 06:15:40 +04:00
outf . write ( ' dwLogLevel : %d \n ' % serverinfo . dwLogLevel )
outf . write ( ' dwDebugLevel : %d \n ' % serverinfo . dwDebugLevel )
outf . write ( ' dwForwardTimeout : %d \n ' % serverinfo . dwForwardTimeout )
outf . write ( ' dwRpcPrototol : 0x %x \n ' % serverinfo . dwRpcProtocol )
outf . write ( ' dwNameCheckFlag : %s \n ' % name_check_flag_string ( serverinfo . dwNameCheckFlag ) )
outf . write ( ' cAddressAnswerLimit : %d \n ' % serverinfo . cAddressAnswerLimit )
outf . write ( ' dwRecursionRetry : %d \n ' % serverinfo . dwRecursionRetry )
outf . write ( ' dwRecursionTimeout : %d \n ' % serverinfo . dwRecursionTimeout )
outf . write ( ' dwMaxCacheTtl : %d \n ' % serverinfo . dwMaxCacheTtl )
outf . write ( ' dwDsPollingInterval : %d \n ' % serverinfo . dwDsPollingInterval )
outf . write ( ' dwScavengingInterval : %d \n ' % serverinfo . dwScavengingInterval )
outf . write ( ' dwDefaultRefreshInterval : %d \n ' % serverinfo . dwDefaultRefreshInterval )
outf . write ( ' dwDefaultNoRefreshInterval : %d \n ' % serverinfo . dwDefaultNoRefreshInterval )
outf . write ( ' fAutoReverseZones : %s \n ' % bool_string ( serverinfo . fAutoReverseZones ) )
outf . write ( ' fAutoCacheUpdate : %s \n ' % bool_string ( serverinfo . fAutoCacheUpdate ) )
outf . write ( ' fRecurseAfterForwarding : %s \n ' % bool_string ( serverinfo . fRecurseAfterForwarding ) )
outf . write ( ' fForwardDelegations : %s \n ' % bool_string ( serverinfo . fForwardDelegations ) )
outf . write ( ' fNoRecursion : %s \n ' % bool_string ( serverinfo . fNoRecursion ) )
outf . write ( ' fSecureResponses : %s \n ' % bool_string ( serverinfo . fSecureResponses ) )
outf . write ( ' fRoundRobin : %s \n ' % bool_string ( serverinfo . fRoundRobin ) )
outf . write ( ' fLocalNetPriority : %s \n ' % bool_string ( serverinfo . fLocalNetPriority ) )
outf . write ( ' fBindSecondaries : %s \n ' % bool_string ( serverinfo . fBindSecondaries ) )
outf . write ( ' fWriteAuthorityNs : %s \n ' % bool_string ( serverinfo . fWriteAuthorityNs ) )
outf . write ( ' fStrictFileParsing : %s \n ' % bool_string ( serverinfo . fStrictFileParsing ) )
outf . write ( ' fLooseWildcarding : %s \n ' % bool_string ( serverinfo . fLooseWildcarding ) )
outf . write ( ' fDefaultAgingState : %s \n ' % bool_string ( serverinfo . fDefaultAgingState ) )
if typeid != dnsserver . DNSSRV_TYPEID_SERVER_INFO_W2K :
outf . write ( ' dwRpcStructureVersion : 0x %x \n ' % serverinfo . dwRpcStructureVersion )
outf . write ( ' aipLogFilter : %s \n ' % dns_addr_array_string ( serverinfo . aipLogFilter ) )
outf . write ( ' pwszLogFilePath : %s \n ' % serverinfo . pwszLogFilePath )
outf . write ( ' pszDomainName : %s \n ' % serverinfo . pszDomainName )
outf . write ( ' pszForestName : %s \n ' % serverinfo . pszForestName )
outf . write ( ' pszDomainDirectoryPartition : %s \n ' % serverinfo . pszDomainDirectoryPartition )
outf . write ( ' pszForestDirectoryPartition : %s \n ' % serverinfo . pszForestDirectoryPartition )
outf . write ( ' dwLocalNetPriorityNetMask : 0x %x \n ' % serverinfo . dwLocalNetPriorityNetMask )
outf . write ( ' dwLastScavengeTime : %d \n ' % serverinfo . dwLastScavengeTime )
outf . write ( ' dwEventLogLevel : %d \n ' % serverinfo . dwEventLogLevel )
outf . write ( ' dwLogFileMaxSize : %d \n ' % serverinfo . dwLogFileMaxSize )
outf . write ( ' dwDsForestVersion : %d \n ' % serverinfo . dwDsForestVersion )
outf . write ( ' dwDsDomainVersion : %d \n ' % serverinfo . dwDsDomainVersion )
outf . write ( ' dwDsDsaVersion : %d \n ' % serverinfo . dwDsDsaVersion )
if typeid == dnsserver . DNSSRV_TYPEID_SERVER_INFO :
outf . write ( ' fReadOnlyDC : %s \n ' % bool_string ( serverinfo . fReadOnlyDC ) )
def print_zoneinfo ( outf , typeid , zoneinfo ) :
outf . write ( ' pszZoneName : %s \n ' % zoneinfo . pszZoneName )
outf . write ( ' dwZoneType : %s \n ' % zone_type_string ( zoneinfo . dwZoneType ) )
outf . write ( ' fReverse : %s \n ' % bool_string ( zoneinfo . fReverse ) )
outf . write ( ' fAllowUpdate : %s \n ' % zone_update_string ( zoneinfo . fAllowUpdate ) )
outf . write ( ' fPaused : %s \n ' % bool_string ( zoneinfo . fPaused ) )
outf . write ( ' fShutdown : %s \n ' % bool_string ( zoneinfo . fShutdown ) )
outf . write ( ' fAutoCreated : %s \n ' % bool_string ( zoneinfo . fAutoCreated ) )
outf . write ( ' fUseDatabase : %s \n ' % bool_string ( zoneinfo . fUseDatabase ) )
outf . write ( ' pszDataFile : %s \n ' % zoneinfo . pszDataFile )
if typeid != dnsserver . DNSSRV_TYPEID_ZONE_INFO :
outf . write ( ' aipMasters : %s \n ' %
2018-07-30 09:15:34 +03:00
ip4_array_string ( zoneinfo . aipMasters ) )
2011-10-17 06:15:40 +04:00
else :
outf . write ( ' aipMasters : %s \n ' %
2018-07-30 09:15:34 +03:00
dns_addr_array_string ( zoneinfo . aipMasters ) )
2011-10-17 06:15:40 +04:00
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 ' %
2018-07-30 09:15:34 +03:00
ip4_array_string ( zoneinfo . aipSecondaries ) )
2011-10-17 06:15:40 +04:00
outf . write ( ' aipNotify : %s \n ' %
2018-07-30 09:15:34 +03:00
ip4_array_string ( zoneinfo . aipNotify ) )
2011-10-17 06:15:40 +04:00
else :
outf . write ( ' aipSecondaries : %s \n ' %
2018-07-30 09:15:34 +03:00
dns_addr_array_string ( zoneinfo . aipSecondaries ) )
2011-10-17 06:15:40 +04:00
outf . write ( ' aipNotify : %s \n ' %
2018-07-30 09:15:34 +03:00
dns_addr_array_string ( zoneinfo . aipNotify ) )
2011-10-17 06:15:40 +04:00
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 ( ' dwNoRefreshInterval : %d \n ' % zoneinfo . dwNoRefreshInterval )
outf . write ( ' dwRefreshInterval : %d \n ' % zoneinfo . dwRefreshInterval )
outf . write ( ' dwAvailForScavengeTime : %d \n ' % zoneinfo . dwAvailForScavengeTime )
if typeid != dnsserver . DNSSRV_TYPEID_ZONE_INFO :
outf . write ( ' aipScavengeServers : %s \n ' %
2018-07-30 09:15:34 +03:00
ip4_array_string ( zoneinfo . aipScavengeServers ) )
2011-10-17 06:15:40 +04:00
else :
outf . write ( ' aipScavengeServers : %s \n ' %
2018-07-30 09:15:34 +03:00
dns_addr_array_string ( zoneinfo . aipScavengeServers ) )
2011-10-17 06:15:40 +04:00
if typeid != dnsserver . DNSSRV_TYPEID_ZONE_INFO_W2K :
outf . write ( ' dwRpcStructureVersion : 0x %x \n ' % zoneinfo . dwRpcStructureVersion )
outf . write ( ' dwForwarderTimeout : %d \n ' % zoneinfo . dwForwarderTimeout )
outf . write ( ' fForwarderSlave : %d \n ' % zoneinfo . fForwarderSlave )
if typeid != dnsserver . DNSSRV_TYPEID_ZONE_INFO :
outf . write ( ' aipLocalMasters : %s \n ' %
2018-07-30 09:15:34 +03:00
ip4_array_string ( zoneinfo . aipLocalMasters ) )
2011-10-17 06:15:40 +04:00
else :
outf . write ( ' aipLocalMasters : %s \n ' %
2018-07-30 09:15:34 +03:00
dns_addr_array_string ( zoneinfo . aipLocalMasters ) )
2011-10-17 06:15:40 +04:00
outf . write ( ' dwDpFlags : %s \n ' % dp_flags_string ( zoneinfo . dwDpFlags ) )
outf . write ( ' pszDpFqdn : %s \n ' % zoneinfo . pszDpFqdn )
outf . write ( ' pwszZoneDn : %s \n ' % zoneinfo . pwszZoneDn )
outf . write ( ' dwLastSuccessfulSoaCheck : %d \n ' % zoneinfo . dwLastSuccessfulSoaCheck )
outf . write ( ' dwLastSuccessfulXfr : %d \n ' % zoneinfo . dwLastSuccessfulXfr )
if typeid == dnsserver . DNSSRV_TYPEID_ZONE_INFO :
outf . write ( ' fQueuedForBackgroundLoad : %s \n ' % bool_string ( zoneinfo . fQueuedForBackgroundLoad ) )
outf . write ( ' fBackgroundLoadInProgress : %s \n ' % bool_string ( zoneinfo . fBackgroundLoadInProgress ) )
outf . write ( ' fReadOnlyZone : %s \n ' % bool_string ( zoneinfo . fReadOnlyZone ) )
outf . write ( ' dwLastXfrAttempt : %d \n ' % zoneinfo . dwLastXfrAttempt )
outf . write ( ' dwLastXfrResult : %d \n ' % zoneinfo . dwLastXfrResult )
def print_zone ( outf , typeid , zone ) :
outf . write ( ' pszZoneName : %s \n ' % zone . pszZoneName )
outf . write ( ' Flags : %s \n ' % zone_flags_string ( zone . Flags ) )
outf . write ( ' ZoneType : %s \n ' % zone_type_string ( zone . ZoneType ) )
outf . write ( ' Version : %s \n ' % zone . Version )
if typeid != dnsserver . DNSSRV_TYPEID_ZONE_W2K :
outf . write ( ' dwDpFlags : %s \n ' % dp_flags_string ( zone . dwDpFlags ) )
outf . write ( ' pszDpFqdn : %s \n ' % zone . pszDpFqdn )
def print_enumzones ( outf , typeid , zones ) :
outf . write ( ' %d zone(s) found \n ' % zones . dwZoneCount )
for zone in zones . ZoneArray :
outf . write ( ' \n ' )
print_zone ( outf , typeid , zone )
def print_dns_record ( outf , rec ) :
if rec . wType == dnsp . DNS_TYPE_A :
mesg = ' A: %s ' % ( rec . data )
2011-12-14 08:54:31 +04:00
elif rec . wType == dnsp . DNS_TYPE_AAAA :
mesg = ' AAAA: %s ' % ( rec . data )
elif rec . wType == dnsp . DNS_TYPE_PTR :
mesg = ' PTR: %s ' % ( rec . data . str )
2011-10-17 06:15:40 +04:00
elif rec . wType == dnsp . DNS_TYPE_NS :
mesg = ' NS: %s ' % ( rec . data . str )
elif rec . wType == dnsp . DNS_TYPE_CNAME :
mesg = ' CNAME: %s ' % ( rec . data . str )
elif rec . wType == dnsp . DNS_TYPE_SOA :
2012-12-06 09:10:42 +04:00
mesg = ' SOA: serial= %d , refresh= %d , retry= %d , expire= %d , minttl= %d , ns= %s , email= %s ' % (
2011-10-17 06:15:40 +04:00
rec . data . dwSerialNo ,
rec . data . dwRefresh ,
rec . data . dwRetry ,
rec . data . dwExpire ,
2012-12-06 09:10:42 +04:00
rec . data . dwMinimumTtl ,
2011-10-17 06:15:40 +04:00
rec . data . NamePrimaryServer . str ,
rec . data . ZoneAdministratorEmail . str )
elif rec . wType == dnsp . DNS_TYPE_MX :
2012-02-15 13:56:38 +04:00
mesg = ' MX: %s ( %d ) ' % ( rec . data . nameExchange . str , rec . data . wPreference )
2011-10-17 06:15:40 +04:00
elif rec . wType == dnsp . DNS_TYPE_SRV :
2012-02-15 13:56:38 +04:00
mesg = ' SRV: %s ( %d , %d , %d ) ' % ( rec . data . nameTarget . str , rec . data . wPort ,
rec . data . wPriority , rec . data . wWeight )
2012-02-28 08:14:49 +04:00
elif rec . wType == dnsp . DNS_TYPE_TXT :
slist = [ ' " %s " ' % name . str for name in rec . data . str ]
mesg = ' TXT: %s ' % ' , ' . join ( slist )
else :
mesg = ' Unknown: '
2011-10-17 06:15:40 +04:00
outf . write ( ' %s (flags= %x , serial= %d , ttl= %d ) \n ' % (
mesg , rec . dwFlags , rec . dwSerial , rec . dwTtlSeconds ) )
def print_dnsrecords ( outf , records ) :
for rec in records . rec :
outf . write ( ' Name= %s , Records= %d , Children= %d \n ' % (
rec . dnsNodeName . str ,
rec . wRecordCount ,
rec . dwChildCount ) )
for dns_rec in rec . records :
print_dns_record ( outf , dns_rec )
2012-02-14 06:19:36 +04:00
# Convert data into a dns record
def data_to_dns_record ( record_type , data ) :
2021-03-26 10:41:29 +03:00
try :
rec = record_from_string ( record_type , data )
except DNSParseError as e :
raise CommandError ( * e . args ) from None
2012-02-14 06:19:36 +04:00
return rec
2012-02-14 06:32:57 +04:00
# Match dns name (of type DNS_RPC_NAME)
def dns_name_equal ( n1 , n2 ) :
return n1 . str . rstrip ( ' . ' ) . lower ( ) == n2 . str . rstrip ( ' . ' ) . lower ( )
2012-01-06 03:28:52 +04:00
# Match a dns record with specified data
2011-10-17 06:15:40 +04:00
def dns_record_match ( dns_conn , server , zone , name , record_type , data ) :
2012-02-14 06:32:57 +04:00
urec = data_to_dns_record ( record_type , data )
2011-10-17 06:15:40 +04:00
select_flags = dnsserver . DNS_RPC_VIEW_AUTHORITY_DATA
try :
2012-09-16 16:18:39 +04:00
buflen , res = dns_conn . DnssrvEnumRecords2 (
dnsserver . DNS_CLIENT_VERSION_LONGHORN , 0 , server , zone , name , None ,
record_type , select_flags , None , None )
2016-11-25 06:29:31 +03:00
except WERRORError as e :
2017-02-13 01:12:54 +03:00
if e . args [ 0 ] == werror . WERR_DNS_ERROR_NAME_DOES_NOT_EXIST :
2016-11-25 06:29:31 +03:00
# Either the zone doesn't exist, or there were no records.
# We can't differentiate the two.
return None
raise e
2011-10-17 06:15:40 +04:00
2012-01-06 03:28:52 +04:00
if not res or res . count == 0 :
return None
for rec in res . rec [ 0 ] . records :
if rec . wType != record_type :
continue
2011-10-17 06:15:40 +04:00
found = False
if record_type == dnsp . DNS_TYPE_A :
2012-02-14 06:32:57 +04:00
if rec . data == urec . data :
2011-10-17 06:15:40 +04:00
found = True
elif record_type == dnsp . DNS_TYPE_AAAA :
2012-02-14 06:32:57 +04:00
if rec . data == urec . data :
2011-10-17 06:15:40 +04:00
found = True
2011-12-14 08:54:31 +04:00
elif record_type == dnsp . DNS_TYPE_PTR :
2012-02-14 06:32:57 +04:00
if dns_name_equal ( rec . data , urec . data ) :
2011-12-14 08:54:31 +04:00
found = True
2011-10-17 06:15:40 +04:00
elif record_type == dnsp . DNS_TYPE_CNAME :
2012-02-14 06:32:57 +04:00
if dns_name_equal ( rec . data , urec . data ) :
2011-10-17 06:15:40 +04:00
found = True
elif record_type == dnsp . DNS_TYPE_NS :
2012-02-14 06:32:57 +04:00
if dns_name_equal ( rec . data , urec . data ) :
found = True
elif record_type == dnsp . DNS_TYPE_MX :
if dns_name_equal ( rec . data . nameExchange , urec . data . nameExchange ) and \
rec . data . wPreference == urec . data . wPreference :
found = True
elif record_type == dnsp . DNS_TYPE_SRV :
if rec . data . wPriority == urec . data . wPriority and \
rec . data . wWeight == urec . data . wWeight and \
rec . data . wPort == urec . data . wPort and \
dns_name_equal ( rec . data . nameTarget , urec . data . nameTarget ) :
found = True
elif record_type == dnsp . DNS_TYPE_SOA :
if rec . data . dwSerialNo == urec . data . dwSerialNo and \
rec . data . dwRefresh == urec . data . dwRefresh and \
rec . data . dwRetry == urec . data . dwRetry and \
rec . data . dwExpire == urec . data . dwExpire and \
rec . data . dwMinimumTtl == urec . data . dwMinimumTtl and \
dns_name_equal ( rec . data . NamePrimaryServer ,
urec . data . NamePrimaryServer ) and \
dns_name_equal ( rec . data . ZoneAdministratorEmail ,
urec . data . ZoneAdministratorEmail ) :
2011-10-17 06:15:40 +04:00
found = True
2012-02-28 08:14:49 +04:00
elif record_type == dnsp . DNS_TYPE_TXT :
if rec . data . count == urec . data . count :
found = True
2018-05-04 14:19:57 +03:00
for i in range ( rec . data . count ) :
2012-02-28 08:14:49 +04:00
found = found and \
( rec . data . str [ i ] . str == urec . data . str [ i ] . str )
2011-10-17 06:15:40 +04:00
if found :
2016-11-25 06:29:31 +03:00
return rec
2011-10-17 06:15:40 +04:00
2016-11-25 06:29:31 +03:00
return None
2011-10-17 06:15:40 +04:00
class cmd_serverinfo ( Command ) :
2012-10-08 14:32:58 +04:00
""" Query for Server information. """
2011-10-17 06:15:40 +04:00
synopsis = ' % prog <server> [options] '
2018-07-30 09:17:02 +03:00
takes_args = [ ' server ' ]
2011-10-17 06:15:40 +04:00
2012-02-07 10:27:18 +04:00
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" versionopts " : options . VersionOptions ,
" credopts " : options . CredentialsOptions ,
}
2011-10-17 06:15:40 +04:00
takes_options = [
2011-10-21 04:27:28 +04:00
Option ( ' --client-version ' , help = ' Client Version ' ,
2018-07-30 09:15:34 +03:00
default = ' longhorn ' , metavar = ' w2k|dotnet|longhorn ' ,
2018-07-30 09:19:05 +03:00
choices = [ ' w2k ' , ' dotnet ' , ' longhorn ' ] , dest = ' cli_ver ' ) ,
2011-10-17 06:15:40 +04:00
]
2012-09-16 16:18:39 +04:00
def run ( self , server , cli_ver , sambaopts = None , credopts = None ,
versionopts = None ) :
2011-10-17 06:15:40 +04:00
self . lp = sambaopts . get_loadparm ( )
self . creds = credopts . get_credentials ( self . lp )
dns_conn = dns_connect ( server , self . lp , self . creds )
client_version = dns_client_version ( cli_ver )
2012-09-16 16:18:39 +04:00
typeid , res = dns_conn . DnssrvQuery2 ( client_version , 0 , server ,
None , ' ServerInfo ' )
2011-10-17 06:15:40 +04:00
print_serverinfo ( self . outf , typeid , res )
class cmd_zoneinfo ( Command ) :
2012-10-08 14:32:58 +04:00
""" Query for zone information. """
2011-10-17 06:15:40 +04:00
synopsis = ' % prog <server> <zone> [options] '
2018-07-30 09:17:02 +03:00
takes_args = [ ' server ' , ' zone ' ]
2011-10-17 06:15:40 +04:00
2012-02-07 10:27:18 +04:00
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" versionopts " : options . VersionOptions ,
" credopts " : options . CredentialsOptions ,
}
2011-10-17 06:15:40 +04:00
takes_options = [
2011-10-21 04:27:28 +04:00
Option ( ' --client-version ' , help = ' Client Version ' ,
2018-07-30 09:15:34 +03:00
default = ' longhorn ' , metavar = ' w2k|dotnet|longhorn ' ,
2018-07-30 09:19:05 +03:00
choices = [ ' w2k ' , ' dotnet ' , ' longhorn ' ] , dest = ' cli_ver ' ) ,
2011-10-17 06:15:40 +04:00
]
2012-09-16 16:18:39 +04:00
def run ( self , server , zone , cli_ver , sambaopts = None , credopts = None ,
versionopts = None ) :
2011-10-17 06:15:40 +04:00
self . lp = sambaopts . get_loadparm ( )
self . creds = credopts . get_credentials ( self . lp )
dns_conn = dns_connect ( server , self . lp , self . creds )
client_version = dns_client_version ( cli_ver )
2012-09-16 16:18:39 +04:00
typeid , res = dns_conn . DnssrvQuery2 ( client_version , 0 , server , zone ,
2011-10-17 06:15:40 +04:00
' ZoneInfo ' )
print_zoneinfo ( self . outf , typeid , res )
class cmd_zonelist ( Command ) :
2012-10-08 14:32:58 +04:00
""" Query for zones. """
2011-10-17 06:15:40 +04:00
synopsis = ' % prog <server> [options] '
2018-07-30 09:17:02 +03:00
takes_args = [ ' server ' ]
2011-10-17 06:15:40 +04:00
2012-02-07 10:27:18 +04:00
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" versionopts " : options . VersionOptions ,
" credopts " : options . CredentialsOptions ,
}
2011-10-17 06:15:40 +04:00
takes_options = [
2011-10-21 04:27:28 +04:00
Option ( ' --client-version ' , help = ' Client Version ' ,
2018-07-30 09:15:34 +03:00
default = ' longhorn ' , metavar = ' w2k|dotnet|longhorn ' ,
2018-07-30 09:19:05 +03:00
choices = [ ' w2k ' , ' dotnet ' , ' longhorn ' ] , dest = ' cli_ver ' ) ,
2011-10-17 06:15:40 +04:00
Option ( ' --primary ' , help = ' List primary zones (default) ' ,
2018-07-30 09:15:34 +03:00
action = ' store_true ' , dest = ' primary ' ) ,
2011-10-17 06:15:40 +04:00
Option ( ' --secondary ' , help = ' List secondary zones ' ,
2018-07-30 09:15:34 +03:00
action = ' store_true ' , dest = ' secondary ' ) ,
2011-10-17 06:15:40 +04:00
Option ( ' --cache ' , help = ' List cached zones ' ,
2018-07-30 09:15:34 +03:00
action = ' store_true ' , dest = ' cache ' ) ,
2011-10-17 06:15:40 +04:00
Option ( ' --auto ' , help = ' List automatically created zones ' ,
2018-07-30 09:15:34 +03:00
action = ' store_true ' , dest = ' auto ' ) ,
2011-10-17 06:15:40 +04:00
Option ( ' --forward ' , help = ' List forward zones ' ,
2018-07-30 09:15:34 +03:00
action = ' store_true ' , dest = ' forward ' ) ,
2011-10-17 06:15:40 +04:00
Option ( ' --reverse ' , help = ' List reverse zones ' ,
2018-07-30 09:15:34 +03:00
action = ' store_true ' , dest = ' reverse ' ) ,
2011-10-17 06:15:40 +04:00
Option ( ' --ds ' , help = ' List directory integrated zones ' ,
2018-07-30 09:15:34 +03:00
action = ' store_true ' , dest = ' ds ' ) ,
2011-10-17 06:15:40 +04:00
Option ( ' --non-ds ' , help = ' List non-directory zones ' ,
2018-07-30 09:15:34 +03:00
action = ' store_true ' , dest = ' nonds ' )
2011-10-17 06:15:40 +04:00
]
def run ( self , server , cli_ver , primary = False , secondary = False , cache = False ,
2018-07-30 09:15:34 +03:00
auto = False , forward = False , reverse = False , ds = False , nonds = False ,
sambaopts = None , credopts = None , versionopts = None ) :
2011-10-17 06:15:40 +04:00
request_filter = 0
if primary :
request_filter | = dnsserver . DNS_ZONE_REQUEST_PRIMARY
if secondary :
request_filter | = dnsserver . DNS_ZONE_REQUEST_SECONDARY
if cache :
request_filter | = dnsserver . DNS_ZONE_REQUEST_CACHE
if auto :
request_filter | = dnsserver . DNS_ZONE_REQUEST_AUTO
if forward :
request_filter | = dnsserver . DNS_ZONE_REQUEST_FORWARD
if reverse :
request_filter | = dnsserver . DNS_ZONE_REQUEST_REVERSE
if ds :
request_filter | = dnsserver . DNS_ZONE_REQUEST_DS
if nonds :
request_filter | = dnsserver . DNS_ZONE_REQUEST_NON_DS
if request_filter == 0 :
request_filter = dnsserver . DNS_ZONE_REQUEST_PRIMARY
self . lp = sambaopts . get_loadparm ( )
self . creds = credopts . get_credentials ( self . lp )
dns_conn = dns_connect ( server , self . lp , self . creds )
client_version = dns_client_version ( cli_ver )
typeid , res = dns_conn . DnssrvComplexOperation2 ( client_version ,
2018-07-30 09:15:34 +03:00
0 , server , None ,
' EnumZones ' ,
dnsserver . DNSSRV_TYPEID_DWORD ,
request_filter )
2011-10-17 06:15:40 +04:00
if client_version == dnsserver . DNS_CLIENT_VERSION_W2K :
typeid = dnsserver . DNSSRV_TYPEID_ZONE_W2K
else :
typeid = dnsserver . DNSSRV_TYPEID_ZONE
print_enumzones ( self . outf , typeid , res )
2011-12-20 05:06:47 +04:00
class cmd_zonecreate ( Command ) :
2012-10-08 14:32:58 +04:00
""" Create a zone. """
2011-12-20 05:06:47 +04:00
synopsis = ' % prog <server> <zone> [options] '
2018-07-30 09:17:02 +03:00
takes_args = [ ' server ' , ' zone ' ]
2011-12-20 05:06:47 +04:00
2012-02-07 10:27:18 +04:00
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" versionopts " : options . VersionOptions ,
" credopts " : options . CredentialsOptions ,
}
2011-12-20 05:06:47 +04:00
takes_options = [
Option ( ' --client-version ' , help = ' Client Version ' ,
2018-07-30 09:15:34 +03:00
default = ' longhorn ' , metavar = ' w2k|dotnet|longhorn ' ,
2018-07-30 09:19:05 +03:00
choices = [ ' w2k ' , ' dotnet ' , ' longhorn ' ] , dest = ' cli_ver ' )
2011-12-20 05:06:47 +04:00
]
def run ( self , server , zone , cli_ver , sambaopts = None , credopts = None ,
versionopts = None ) :
self . lp = sambaopts . get_loadparm ( )
self . creds = credopts . get_credentials ( self . lp )
dns_conn = dns_connect ( server , self . lp , self . creds )
zone = zone . lower ( )
client_version = dns_client_version ( cli_ver )
if client_version == dnsserver . DNS_CLIENT_VERSION_W2K :
typeid = dnsserver . DNSSRV_TYPEID_ZONE_CREATE_W2K
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 . fAging = 0
2013-05-27 06:26:36 +04:00
zone_create_info . fDsIntegrated = 1
zone_create_info . fLoadExisting = 1
2011-12-20 05:06:47 +04:00
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 . fAging = 0
2013-05-27 06:26:36 +04:00
zone_create_info . fDsIntegrated = 1
zone_create_info . fLoadExisting = 1
2011-12-20 05:06:47 +04:00
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 . fAging = 0
2013-05-27 06:26:36 +04:00
zone_create_info . fDsIntegrated = 1
zone_create_info . fLoadExisting = 1
2011-12-20 05:06:47 +04:00
zone_create_info . dwDpFlags = dnsserver . DNS_DP_DOMAIN_DEFAULT
2012-09-16 16:18:39 +04:00
res = dns_conn . DnssrvOperation2 ( client_version , 0 , server , None ,
0 , ' ZoneCreate ' , typeid ,
2011-12-20 05:06:47 +04:00
zone_create_info )
2013-05-27 06:37:20 +04:00
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
2016-11-25 06:29:31 +03:00
try :
res = dns_conn . DnssrvOperation2 ( client_version , 0 , server , zone ,
0 , ' ResetDwordProperty ' , typeid ,
name_and_param )
except WERRORError as e :
2017-02-13 01:12:54 +03:00
if e . args [ 0 ] == werror . WERR_DNS_ERROR_ZONE_ALREADY_EXISTS :
2016-11-25 06:29:31 +03:00
self . outf . write ( ' Zone already exists. ' )
raise e
2011-12-20 05:06:47 +04:00
self . outf . write ( ' Zone %s created successfully \n ' % zone )
class cmd_zonedelete ( Command ) :
2012-10-08 14:32:58 +04:00
""" Delete a zone. """
2011-12-20 05:06:47 +04:00
synopsis = ' % prog <server> <zone> [options] '
2018-07-30 09:17:02 +03:00
takes_args = [ ' server ' , ' zone ' ]
2011-12-20 05:06:47 +04:00
2012-02-07 10:27:18 +04:00
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" versionopts " : options . VersionOptions ,
" credopts " : options . CredentialsOptions ,
}
2012-09-16 16:18:39 +04:00
def run ( self , server , zone , sambaopts = None , credopts = None ,
versionopts = None ) :
2011-12-20 05:06:47 +04:00
self . lp = sambaopts . get_loadparm ( )
self . creds = credopts . get_credentials ( self . lp )
dns_conn = dns_connect ( server , self . lp , self . creds )
zone = zone . lower ( )
2016-11-25 06:29:31 +03:00
try :
res = dns_conn . DnssrvOperation2 ( dnsserver . DNS_CLIENT_VERSION_LONGHORN ,
0 , server , zone , 0 , ' DeleteZoneFromDs ' ,
dnsserver . DNSSRV_TYPEID_NULL ,
None )
except WERRORError as e :
2017-02-13 01:12:54 +03:00
if e . args [ 0 ] == werror . WERR_DNS_ERROR_ZONE_DOES_NOT_EXIST :
2018-12-18 14:58:53 +03:00
raise CommandError ( ' Zone does not exist and so could not be deleted. ' )
2016-11-25 06:29:31 +03:00
raise e
self . outf . write ( ' Zone %s deleted successfully \n ' % zone )
2011-12-20 05:06:47 +04:00
2011-10-17 06:15:40 +04:00
class cmd_query ( Command ) :
2011-10-21 04:27:28 +04:00
""" Query a name. """
2011-10-17 06:15:40 +04:00
2020-06-05 09:56:21 +03:00
synopsis = ( ' % prog <server> <zone> <name> '
' <A|AAAA|PTR|CNAME|MX|NS|SOA|SRV|TXT|ALL> [options] ' )
2011-10-17 06:15:40 +04:00
2018-07-30 09:17:02 +03:00
takes_args = [ ' server ' , ' zone ' , ' name ' , ' rtype ' ]
2011-10-17 06:15:40 +04:00
2012-02-07 10:27:18 +04:00
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" versionopts " : options . VersionOptions ,
" credopts " : options . CredentialsOptions ,
}
2011-10-17 06:15:40 +04:00
takes_options = [
Option ( ' --authority ' , help = ' Search authoritative records (default) ' ,
2018-07-30 09:15:34 +03:00
action = ' store_true ' , dest = ' authority ' ) ,
2011-10-17 06:15:40 +04:00
Option ( ' --cache ' , help = ' Search cached records ' ,
2018-07-30 09:15:34 +03:00
action = ' store_true ' , dest = ' cache ' ) ,
2011-10-17 06:15:40 +04:00
Option ( ' --glue ' , help = ' Search glue records ' ,
2018-07-30 09:15:34 +03:00
action = ' store_true ' , dest = ' glue ' ) ,
2011-10-17 06:15:40 +04:00
Option ( ' --root ' , help = ' Search root hints ' ,
2018-07-30 09:15:34 +03:00
action = ' store_true ' , dest = ' root ' ) ,
2011-10-17 06:15:40 +04:00
Option ( ' --additional ' , help = ' List additional records ' ,
2018-07-30 09:15:34 +03:00
action = ' store_true ' , dest = ' additional ' ) ,
2011-10-17 06:15:40 +04:00
Option ( ' --no-children ' , help = ' Do not list children ' ,
2018-07-30 09:15:34 +03:00
action = ' store_true ' , dest = ' no_children ' ) ,
2011-10-17 06:15:40 +04:00
Option ( ' --only-children ' , help = ' List only children ' ,
2018-07-30 09:15:34 +03:00
action = ' store_true ' , dest = ' only_children ' )
2011-10-17 06:15:40 +04:00
]
2012-09-16 16:18:39 +04:00
def run ( self , server , zone , name , rtype , authority = False , cache = False ,
glue = False , root = False , additional = False , no_children = False ,
only_children = False , sambaopts = None , credopts = None ,
versionopts = None ) :
2011-10-17 06:15:40 +04:00
record_type = dns_type_flag ( rtype )
2013-08-02 12:53:56 +04:00
if name . find ( ' * ' ) != - 1 :
2017-07-20 00:13:43 +03:00
self . outf . write ( ' use " @ " to dump entire domain, looking up %s \n ' %
name )
2013-08-02 12:53:56 +04:00
2011-10-17 06:15:40 +04:00
select_flags = 0
if authority :
select_flags | = dnsserver . DNS_RPC_VIEW_AUTHORITY_DATA
if cache :
select_flags | = dnsserver . DNS_RPC_VIEW_CACHE_DATA
if glue :
select_flags | = dnsserver . DNS_RPC_VIEW_GLUE_DATA
if root :
select_flags | = dnsserver . DNS_RPC_VIEW_ROOT_HINT_DATA
if additional :
select_flags | = dnsserver . DNS_RPC_VIEW_ADDITIONAL_DATA
if no_children :
select_flags | = dnsserver . DNS_RPC_VIEW_NO_CHILDREN
if only_children :
select_flags | = dnsserver . DNS_RPC_VIEW_ONLY_CHILDREN
if select_flags == 0 :
select_flags = dnsserver . DNS_RPC_VIEW_AUTHORITY_DATA
2011-10-21 04:27:28 +04:00
if select_flags == dnsserver . DNS_RPC_VIEW_ADDITIONAL_DATA :
self . outf . write ( ' Specify either --authority or --root along with --additional. \n ' )
self . outf . write ( ' Assuming --authority. \n ' )
select_flags | = dnsserver . DNS_RPC_VIEW_AUTHORITY_DATA
2011-10-17 06:15:40 +04:00
self . lp = sambaopts . get_loadparm ( )
self . creds = credopts . get_credentials ( self . lp )
dns_conn = dns_connect ( server , self . lp , self . creds )
2016-11-25 06:29:31 +03:00
try :
buflen , res = dns_conn . DnssrvEnumRecords2 (
2012-09-16 16:18:39 +04:00
dnsserver . DNS_CLIENT_VERSION_LONGHORN , 0 , server , zone , name ,
None , record_type , select_flags , None , None )
2016-11-25 06:29:31 +03:00
except WERRORError as e :
2017-02-13 01:12:54 +03:00
if e . args [ 0 ] == werror . WERR_DNS_ERROR_NAME_DOES_NOT_EXIST :
2018-12-18 14:58:53 +03:00
raise CommandError ( ' Record or zone does not exist. ' )
2016-11-25 06:29:31 +03:00
raise e
2011-10-17 06:15:40 +04:00
print_dnsrecords ( self . outf , res )
class cmd_roothints ( Command ) :
2012-10-08 14:32:58 +04:00
""" Query root hints. """
2011-10-17 06:15:40 +04:00
synopsis = ' % prog <server> [<name>] [options] '
2018-07-30 09:17:02 +03:00
takes_args = [ ' server ' , ' name? ' ]
2011-10-17 06:15:40 +04:00
2012-02-07 10:27:18 +04:00
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" versionopts " : options . VersionOptions ,
" credopts " : options . CredentialsOptions ,
}
2012-09-16 16:18:39 +04:00
def run ( self , server , name = ' . ' , sambaopts = None , credopts = None ,
versionopts = None ) :
2011-10-17 06:15:40 +04:00
record_type = dnsp . DNS_TYPE_NS
select_flags = ( dnsserver . DNS_RPC_VIEW_ROOT_HINT_DATA |
dnsserver . DNS_RPC_VIEW_ADDITIONAL_DATA )
self . lp = sambaopts . get_loadparm ( )
self . creds = credopts . get_credentials ( self . lp )
dns_conn = dns_connect ( server , self . lp , self . creds )
2012-09-16 16:18:39 +04:00
buflen , res = dns_conn . DnssrvEnumRecords2 (
dnsserver . DNS_CLIENT_VERSION_LONGHORN , 0 , server , ' ..RootHints ' ,
name , None , record_type , select_flags , None , None )
2011-10-17 06:15:40 +04:00
print_dnsrecords ( self . outf , res )
class cmd_add_record ( Command ) :
2012-02-14 06:41:45 +04:00
""" Add a DNS record
2011-10-17 06:15:40 +04:00
2012-02-14 06:41:45 +04:00
For each type data contents are as follows :
A ipv4_address_string
AAAA ipv6_address_string
PTR fqdn_string
CNAME fqdn_string
NS fqdn_string
MX " fqdn_string preference "
SRV " fqdn_string port priority weight "
2012-02-28 08:14:49 +04:00
TXT " ' string1 ' ' string2 ' ... "
2012-02-14 06:41:45 +04:00
"""
2012-02-28 08:14:49 +04:00
synopsis = ' % prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SRV|TXT> <data> '
2011-10-17 06:15:40 +04:00
2018-07-30 09:17:02 +03:00
takes_args = [ ' server ' , ' zone ' , ' name ' , ' rtype ' , ' data ' ]
2011-10-17 06:15:40 +04:00
2012-02-07 10:27:18 +04:00
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" versionopts " : options . VersionOptions ,
" credopts " : options . CredentialsOptions ,
}
2012-09-16 16:18:39 +04:00
def run ( self , server , zone , name , rtype , data , sambaopts = None ,
credopts = None , versionopts = None ) :
2011-10-17 06:15:40 +04:00
2018-07-30 09:19:05 +03:00
if rtype . upper ( ) not in ( ' A ' , ' AAAA ' , ' PTR ' , ' CNAME ' , ' NS ' , ' MX ' , ' SRV ' , ' TXT ' ) :
2011-10-17 06:15:40 +04:00
raise CommandError ( ' Adding record of type %s is not supported ' % rtype )
2012-02-14 06:41:45 +04:00
record_type = dns_type_flag ( rtype )
rec = data_to_dns_record ( record_type , data )
2011-10-17 06:15:40 +04:00
self . lp = sambaopts . get_loadparm ( )
self . creds = credopts . get_credentials ( self . lp )
dns_conn = dns_connect ( server , self . lp , self . creds )
add_rec_buf = dnsserver . DNS_RPC_RECORD_BUF ( )
add_rec_buf . rec = rec
2016-11-25 06:29:31 +03:00
try :
dns_conn . DnssrvUpdateRecord2 ( dnsserver . DNS_CLIENT_VERSION_LONGHORN ,
0 , server , zone , name , add_rec_buf , None )
except WERRORError as e :
2017-02-13 01:12:54 +03:00
if e . args [ 0 ] == werror . WERR_DNS_ERROR_NAME_DOES_NOT_EXIST :
2019-11-05 13:23:48 +03:00
raise CommandError ( ' Zone does not exist; record could not be added. zone[ %s ] name[ %s ] ' % ( zone , name ) )
if e . args [ 0 ] == werror . WERR_DNS_ERROR_RECORD_ALREADY_EXISTS :
raise CommandError ( ' Record already exist; record could not be added. zone[ %s ] name[ %s ] ' % ( zone , name ) )
2016-11-25 06:29:31 +03:00
raise e
2011-12-20 05:07:11 +04:00
self . outf . write ( ' Record added successfully \n ' )
2011-10-17 06:15:40 +04:00
class cmd_update_record ( Command ) :
2012-02-14 06:41:45 +04:00
""" Update a DNS record
For each type data contents are as follows :
A ipv4_address_string
AAAA ipv6_address_string
PTR fqdn_string
CNAME fqdn_string
NS fqdn_string
MX " fqdn_string preference "
2012-12-06 09:11:18 +04:00
SOA " fqdn_dns fqdn_email serial refresh retry expire minimumttl "
2012-02-14 06:41:45 +04:00
SRV " fqdn_string port priority weight "
2012-02-28 08:14:49 +04:00
TXT " ' string1 ' ' string2 ' ... "
2012-02-14 06:41:45 +04:00
"""
2011-10-17 06:15:40 +04:00
2012-12-06 09:11:18 +04:00
synopsis = ' % prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SOA|SRV|TXT> <olddata> <newdata> '
2011-10-17 06:15:40 +04:00
2018-07-30 09:17:02 +03:00
takes_args = [ ' server ' , ' zone ' , ' name ' , ' rtype ' , ' olddata ' , ' newdata ' ]
2011-10-17 06:15:40 +04:00
2012-02-07 10:27:18 +04:00
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" versionopts " : options . VersionOptions ,
" credopts " : options . CredentialsOptions ,
}
2011-10-17 06:15:40 +04:00
def run ( self , server , zone , name , rtype , olddata , newdata ,
2018-07-30 09:15:34 +03:00
sambaopts = None , credopts = None , versionopts = None ) :
2011-10-17 06:15:40 +04:00
2018-07-30 09:19:05 +03:00
if rtype . upper ( ) not in ( ' A ' , ' AAAA ' , ' PTR ' , ' CNAME ' , ' NS ' , ' MX ' , ' SOA ' , ' SRV ' , ' TXT ' ) :
2011-10-17 06:15:40 +04:00
raise CommandError ( ' Updating record of type %s is not supported ' % rtype )
2012-02-14 06:41:45 +04:00
record_type = dns_type_flag ( rtype )
rec = data_to_dns_record ( record_type , newdata )
2011-10-17 06:15:40 +04:00
self . lp = sambaopts . get_loadparm ( )
self . creds = credopts . get_credentials ( self . lp )
dns_conn = dns_connect ( server , self . lp , self . creds )
2012-09-16 16:18:39 +04:00
rec_match = dns_record_match ( dns_conn , server , zone , name , record_type ,
2018-07-30 09:16:12 +03:00
olddata )
2011-10-17 06:15:40 +04:00
if not rec_match :
2016-11-25 06:29:31 +03:00
raise CommandError ( ' Record or zone does not exist. ' )
2011-10-17 06:15:40 +04:00
# Copy properties from existing record to new record
rec . dwFlags = rec_match . dwFlags
rec . dwSerial = rec_match . dwSerial
rec . dwTtlSeconds = rec_match . dwTtlSeconds
rec . dwTimeStamp = rec_match . dwTimeStamp
add_rec_buf = dnsserver . DNS_RPC_RECORD_BUF ( )
add_rec_buf . rec = rec
del_rec_buf = dnsserver . DNS_RPC_RECORD_BUF ( )
del_rec_buf . rec = rec_match
2016-11-25 06:29:31 +03:00
try :
dns_conn . DnssrvUpdateRecord2 ( dnsserver . DNS_CLIENT_VERSION_LONGHORN ,
0 ,
server ,
zone ,
name ,
add_rec_buf ,
del_rec_buf )
except WERRORError as e :
2017-02-13 01:12:54 +03:00
if e . args [ 0 ] == werror . WERR_DNS_ERROR_NAME_DOES_NOT_EXIST :
2018-12-18 14:58:53 +03:00
raise CommandError ( ' Zone does not exist; record could not be updated. ' )
2016-11-25 06:29:31 +03:00
raise e
2013-04-18 12:32:44 +04:00
self . outf . write ( ' Record updated successfully \n ' )
2011-10-17 06:15:40 +04:00
class cmd_delete_record ( Command ) :
2012-02-14 06:41:45 +04:00
""" Delete a DNS record
For each type data contents are as follows :
A ipv4_address_string
AAAA ipv6_address_string
PTR fqdn_string
CNAME fqdn_string
NS fqdn_string
MX " fqdn_string preference "
SRV " fqdn_string port priority weight "
2012-02-28 08:14:49 +04:00
TXT " ' string1 ' ' string2 ' ... "
2012-02-14 06:41:45 +04:00
"""
2011-10-17 06:15:40 +04:00
2012-02-28 08:14:49 +04:00
synopsis = ' % prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SRV|TXT> <data> '
2011-10-17 06:15:40 +04:00
2018-07-30 09:17:02 +03:00
takes_args = [ ' server ' , ' zone ' , ' name ' , ' rtype ' , ' data ' ]
2011-10-17 06:15:40 +04:00
2012-02-07 10:27:18 +04:00
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" versionopts " : options . VersionOptions ,
" credopts " : options . CredentialsOptions ,
}
2011-10-17 06:15:40 +04:00
def run ( self , server , zone , name , rtype , data , sambaopts = None , credopts = None , versionopts = None ) :
2018-07-30 09:19:05 +03:00
if rtype . upper ( ) not in ( ' A ' , ' AAAA ' , ' PTR ' , ' CNAME ' , ' NS ' , ' MX ' , ' SRV ' , ' TXT ' ) :
2011-10-17 06:15:40 +04:00
raise CommandError ( ' Deleting record of type %s is not supported ' % rtype )
2012-02-14 06:41:45 +04:00
record_type = dns_type_flag ( rtype )
2016-11-28 01:12:18 +03:00
rec = data_to_dns_record ( record_type , data )
2012-02-14 06:41:45 +04:00
2011-10-17 06:15:40 +04:00
self . lp = sambaopts . get_loadparm ( )
self . creds = credopts . get_credentials ( self . lp )
dns_conn = dns_connect ( server , self . lp , self . creds )
del_rec_buf = dnsserver . DNS_RPC_RECORD_BUF ( )
2016-11-28 01:12:18 +03:00
del_rec_buf . rec = rec
2011-10-17 06:15:40 +04:00
2016-11-25 06:29:31 +03:00
try :
dns_conn . DnssrvUpdateRecord2 ( dnsserver . DNS_CLIENT_VERSION_LONGHORN ,
0 ,
server ,
zone ,
name ,
None ,
del_rec_buf )
except WERRORError as e :
2017-02-13 01:12:54 +03:00
if e . args [ 0 ] == werror . WERR_DNS_ERROR_NAME_DOES_NOT_EXIST :
2019-11-05 13:23:48 +03:00
raise CommandError ( ' Zone does not exist; record could not be deleted. zone[ %s ] name[ %s ] ' % ( zone , name ) )
if e . args [ 0 ] == werror . WERR_DNS_ERROR_RECORD_DOES_NOT_EXIST :
raise CommandError ( ' Record does not exist; record could not be deleted. zone[ %s ] name[ %s ] ' % ( zone , name ) )
2016-11-25 06:29:31 +03:00
raise e
2013-04-18 12:32:44 +04:00
self . outf . write ( ' Record deleted successfully \n ' )
2011-10-17 06:15:40 +04:00
2018-01-12 04:14:00 +03:00
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
2018-01-31 06:12:05 +03:00
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 .
2018-01-12 04:14:00 +03:00
"""
synopsis = ' % prog <server> <dnshostname> '
takes_args = [ ' server ' , ' dnshostname ' ]
takes_optiongroups = {
" sambaopts " : options . SambaOptions ,
" versionopts " : options . VersionOptions ,
" credopts " : options . CredentialsOptions ,
}
2018-04-19 07:43:50 +03:00
takes_options = [
Option ( " -v " , " --verbose " , help = " Be verbose " , action = " store_true " ) ,
Option ( " -q " , " --quiet " , help = " Be quiet " , action = " store_true " ) ,
]
2018-01-12 04:14:00 +03:00
def run ( self , server , dnshostname , sambaopts = None , credopts = None ,
versionopts = None , verbose = False , quiet = False ) :
lp = sambaopts . get_loadparm ( )
creds = credopts . get_credentials ( lp )
2018-08-21 03:45:15 +03:00
logger = self . get_logger ( verbose = verbose , quiet = quiet )
2018-01-12 04:14:00 +03:00
samdb = SamDB ( url = " ldap:// %s " % server ,
session_info = system_session ( ) ,
credentials = creds , lp = lp )
2018-01-31 01:52:34 +03:00
remove_dc . remove_dns_references ( samdb , logger , dnshostname ,
ignore_no_name = True )
2018-01-12 04:14:00 +03:00
2011-10-17 06:15:40 +04:00
class cmd_dns ( SuperCommand ) :
2012-10-08 14:32:58 +04:00
""" Domain Name Service (DNS) management. """
2011-10-17 06:15:40 +04:00
subcommands = { }
subcommands [ ' serverinfo ' ] = cmd_serverinfo ( )
subcommands [ ' zoneinfo ' ] = cmd_zoneinfo ( )
subcommands [ ' zonelist ' ] = cmd_zonelist ( )
2011-12-20 05:06:47 +04:00
subcommands [ ' zonecreate ' ] = cmd_zonecreate ( )
subcommands [ ' zonedelete ' ] = cmd_zonedelete ( )
2011-10-17 06:15:40 +04:00
subcommands [ ' query ' ] = cmd_query ( )
subcommands [ ' roothints ' ] = cmd_roothints ( )
subcommands [ ' add ' ] = cmd_add_record ( )
subcommands [ ' update ' ] = cmd_update_record ( )
subcommands [ ' delete ' ] = cmd_delete_record ( )
2018-01-12 04:14:00 +03:00
subcommands [ ' cleanup ' ] = cmd_cleanup_record ( )