Add the no-append-root option.
record is changed.
.P
Haeredes can alert administrators when NS/MX records are changed.
+.SH NORMALIZATION
+.P
+By default, domain/hostnames given will be normalized in two ways:
+.IP \[bu] 2
+All names will be lowercased.
+
+.IP \[bu]
+All names will have a trailing dot (the DNS root) appended if one is
+not present. This can be controlled with the
+\fB\-\-no\-append\-root\fR flag.
+.SH QUERY RESULTS
+.P
+When Haeredes makes a query for an MX record, the result is parsed
+from the \(dqanswer\(dq section of the response. This is
+straightforward.
+.P
+For NS records, however, there are two sections that may contain
+results. If you query the authoritative nameservers for example.com,
+they will return the response in the \(dqanswer\(dq section, as with
+MX records:
+
+.nf
+.I $ dig +short @a.iana-servers.net example.com NS
+b.iana-servers.net.
+a.iana-servers.net.
+.fi
+.P
+However, if you ask a root server, they will return the response in another section, called \(dqauthority\(dq. The \(dqanswer\(dq section is empty:
+
+.nf
+.I $ dig +short @a.gtld-servers.net example.com NS
+.fi
+.P
+We have to request the \(dqauthority\(dq section explicitly:
+
+.nf
+.I $ dig +noall +authority @a.gtld-servers.net example.com NS
+example.com. 172800 IN NS a.iana-servers.net.
+example.com. 172800 IN NS b.iana-servers.net.
+.fi
+.P
+Given Haeredes' use case, it is useful to combine the two. You can
+query a root server to check the registrar data, or a recursive
+resolver to check the data on the authoritative nameservers.
+.P
+So that's what we do. In NS mode, Haeredes will check both the
+\(dqanswer\(dq and \(dqauthority\(dq sections for results.
.SH OPTIONS
+.IP \fB\-\-no\-append\-root\fR,\ \fB-n\fR
+Don't append a trailing dot to any DNS names. If you know what you're
+doing, this can be used to check relative results. Otherwise, it will
+probably just lead to false positives.
+.SH EXAMPLES
+
.IP \fB\-\-server\fR,\ \fB-s\fR
Use the given DNS server rather than the resolvers listed in
-/etc/resolv.conf.
+/etc/resolv.conf. Either an IP address or a hostname will work.
.SH EXAMPLES
.IP \[bu] 2
.fi
.IP \[bu]
Check orlitzky.com against the expected name servers, using
-d.gtld-servers.net:
+a root nameserver (this checks the registrar configuration):
.nf
-.I $ haeredes --server 199.7.91.13 dns1.viabit.com dns2.viabit.com \\\\
+.I $ haeredes --server d.gtld-servers.net dns1.viabit.com dns2.viabit.com \\\\
.I " <<< \(dqorlitzky.com\(dq"
.fi
.IP \[bu]
therefore important to remove domains from the old mail host as
soon as the MX record is changed.
.
- Haeredes can alert administrators when NS/MX records are changed.
+ Haeredes can alert administrators when NS/MX records are changed. More
+ detail can be found in the man page.
.
/Examples/:
.
import Paths_haeredes (version)
import Data.Version (showVersion)
+-- | Description of the 'NS' mode.
ns_description :: String
ns_description =
"Confirm delegation of NS records. " ++
"This is the default mode."
+-- | Description of the 'MX' mode.
mx_description :: String
mx_description = "Confirm delegation of MX records."
my_summary :: String
my_summary = program_name ++ "-" ++ (showVersion version)
+no_append_root_help :: String
+no_append_root_help =
+ "Don't append a trailing dot to DNS names."
+
+-- | Help string for the --server flag.
server_help :: String
server_help =
- "IP address of server to query " ++
- "(will use resolv.conf if not specified)"
+ "IP address or hostname of server to query " ++
+ "(will use resolv.conf if not specified)."
+-- | The Args type represents the possible command-line options. The
+-- duplication here seems necessary; CmdArgs' magic requires us to
+-- define some things explicitly.
data Args =
- NS { server :: Maybe String, delegates :: [String] } |
- MX { server :: Maybe String, delegates :: [String] }
+ NS { no_append_root :: Bool,
+ server :: Maybe String,
+ delegates :: [String] } |
+ MX { no_append_root :: Bool,
+ server :: Maybe String,
+ delegates :: [String] }
deriving (Data, Show, Typeable)
arg_spec :: Args
name "v",
groupname "Common flags"]
where
- -- The repetition here is necessary, some Template Haskell magic
- -- going on.
+ -- The repetition here is necessary, some CmdArgs magic going on.
ns :: Args
ns = NS {
+ no_append_root = def
+ &= groupname "Common flags"
+ &= help no_append_root_help,
+
server = def
&= groupname "Common flags"
&= typ "IP"
mx :: Args
mx = MX {
+ no_append_root = def
+ &= groupname "Common flags"
+ &= help no_append_root_help,
+
server = def
&= groupname "Common flags"
&= typ "IP"
lookupMX',
lookupNS',
normalize,
+ normalize_case,
resolve_address )
where
lookupMX',
lookupNS',
normalize,
+ normalize_case,
resolve_address )
import ExitCodes (exit_bad_server)
-- Convert these to ByteStrings.
let raw_delegates = map BS.pack (delegates cfg)
+ let normalize_function =
+ if (no_append_root cfg)
+ then normalize_case
+ else normalize
+
-- Normalize the given names and delegates
- let nrml_domains = map normalize raw_domains
- let nrml_delegates = map normalize raw_delegates
+ let nrml_domains = map normalize_function raw_domains
+ let nrml_delegates = map normalize_function raw_delegates
rc <- case (server cfg) of
Nothing -> return defaultResolvConf
rs <- makeResolvSeed rc
let lookup_function = case cfg of
- (NS _ _) -> lookupNS'
- (MX _ _) -> lookupMX'
+ (NS _ _ _) -> lookupNS'
+ (MX _ _ _) -> lookupMX'
_ <- withResolver rs $ \resolver -> do
-- Bad stuff happens if we try to run these lookups in parallel