Add a retry flag
Signed-off-by: Sam Therapy <sam@samtherapy.net>
This commit is contained in:
parent
c3198326ec
commit
20d3196a8c
10 changed files with 367 additions and 248 deletions
16
.vscode/launch.json
vendored
Normal file
16
.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch Package",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "auto",
|
||||
"program": "${fileDirname}",
|
||||
"args": ["+timeout=1"]
|
||||
}
|
||||
]
|
||||
}
|
13
cli/cli.go
13
cli/cli.go
|
@ -46,6 +46,7 @@ func ParseCLI(version string) (Options, error) {
|
|||
reverse = flag.Bool("reverse", false, "do a reverse lookup", flag.OptShorthand('x'))
|
||||
|
||||
timeout = flag.Float32("timeout", 1, "Timeout, in `seconds`")
|
||||
retry = flag.Int("retry", 2, "number of `times` to retry")
|
||||
dnssec = flag.Bool("dnssec", false, "enable DNSSEC", flag.OptShorthand('D'))
|
||||
truncate = flag.Bool("no-truncate", false, "ignore truncation if a UDP request truncates (default= retry with TCP)")
|
||||
|
||||
|
@ -118,6 +119,7 @@ func ParseCLI(version string) (Options, error) {
|
|||
Class: dns.StringToClass[strings.ToUpper(*class)],
|
||||
Name: *query,
|
||||
Timeout: time.Duration(*timeout * float32(time.Second)),
|
||||
Retries: *retry,
|
||||
},
|
||||
Display: Displays{
|
||||
Question: !*noQ,
|
||||
|
@ -128,6 +130,15 @@ func ParseCLI(version string) (Options, error) {
|
|||
},
|
||||
}
|
||||
|
||||
// Set timeout to 0.5 seconds if set below 0.5
|
||||
if float32(opts.Request.Timeout) < (0.5 * float32(time.Second)) {
|
||||
opts.Request.Timeout = (time.Second / 2)
|
||||
}
|
||||
|
||||
if opts.Request.Retries < 0 {
|
||||
opts.Request.Timeout = 0
|
||||
}
|
||||
|
||||
opts.Logger.Info("POSIX flags parsed")
|
||||
opts.Logger.Debug(fmt.Sprintf("%+v", opts))
|
||||
|
||||
|
@ -140,7 +151,7 @@ func ParseCLI(version string) (Options, error) {
|
|||
// This includes the dig-style (+) options
|
||||
err = ParseMiscArgs(flag.Args(), &opts)
|
||||
if err != nil {
|
||||
opts.Logger.Error(err)
|
||||
opts.Logger.Warn(err)
|
||||
return opts, err
|
||||
}
|
||||
opts.Logger.Info("Dig/Drill flags parsed")
|
||||
|
|
41
cli/dig.go
41
cli/dig.go
|
@ -4,14 +4,16 @@ package cli
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Parse dig-like commands and set the options as such.
|
||||
func ParseDig(arg string, opts *Options) error {
|
||||
// returns true if the flag starts with a no
|
||||
isNo := !strings.HasPrefix(arg, "no")
|
||||
opts.Logger.Info("Setting", arg, "to", isNo)
|
||||
opts.Logger.Info("Setting", arg)
|
||||
|
||||
switch arg {
|
||||
// Set DNS query flags
|
||||
|
@ -33,12 +35,22 @@ func ParseDig(arg string, opts *Options) error {
|
|||
opts.Z = isNo
|
||||
// End DNS query flags
|
||||
|
||||
// DNS-over-X
|
||||
case "dnssec", "nodnssec":
|
||||
opts.DNSSEC = isNo
|
||||
case "tcp", "vc", "notcp", "novc":
|
||||
opts.TCP = isNo
|
||||
case "ignore", "noignore":
|
||||
opts.Truncate = isNo
|
||||
case "tls", "notls":
|
||||
opts.TLS = isNo
|
||||
case "dnscrypt", "nodnscrypt":
|
||||
opts.DNSCrypt = isNo
|
||||
case "https", "nohttps":
|
||||
opts.HTTPS = isNo
|
||||
case "quic", "noquic":
|
||||
opts.QUIC = isNo
|
||||
// End DNS-over-X
|
||||
|
||||
// Formatting
|
||||
case "short", "noshort":
|
||||
|
@ -74,7 +86,32 @@ func ParseDig(arg string, opts *Options) error {
|
|||
opts.Display.Statistics = isNo
|
||||
|
||||
default:
|
||||
return fmt.Errorf("dig: unknown flag %s given", arg)
|
||||
// Recursive switch statements WOO
|
||||
switch {
|
||||
case strings.HasPrefix(arg, "timeout"):
|
||||
timeout, err := strconv.Atoi(strings.Split(arg, "=")[1])
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("dig: Invalid timeout value")
|
||||
}
|
||||
|
||||
opts.Request.Timeout = time.Duration(timeout)
|
||||
|
||||
case strings.HasPrefix(arg, "retry"), strings.HasPrefix(arg, "tries"):
|
||||
tries, err := strconv.Atoi(strings.Split(arg, "=")[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("dig: Invalid retry value")
|
||||
}
|
||||
|
||||
if strings.HasPrefix(arg, "tries") {
|
||||
tries++
|
||||
}
|
||||
|
||||
opts.Request.Retries = tries
|
||||
|
||||
default:
|
||||
return fmt.Errorf("dig: unknown flag %s given", arg)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -24,6 +24,10 @@ func FuzzDig(f *testing.F) {
|
|||
"dnssec", "nodnssec",
|
||||
"tcp", "vc", "notcp", "novc",
|
||||
"ignore", "noignore",
|
||||
"tls", "notls",
|
||||
"dnscrypt", "nodnscrypt",
|
||||
"https", "nohttps",
|
||||
"quic", "noquic",
|
||||
"short", "noshort",
|
||||
"json", "nojson",
|
||||
"xml", "noxml",
|
||||
|
|
|
@ -103,7 +103,7 @@ func ParseMiscArgs(args []string, opts *Options) error {
|
|||
resolv, err := conf.GetDNSConfig()
|
||||
if err != nil {
|
||||
// :^)
|
||||
opts.Logger.Error("Could not query system for server. Using default")
|
||||
opts.Logger.Warn("Could not query system for server. Using default")
|
||||
opts.Request.Server = "95.216.99.249"
|
||||
} else {
|
||||
// Make sure that if IPv4 or IPv6 is asked for it actually uses it
|
||||
|
|
494
doc/awl.1
494
doc/awl.1
|
@ -1,232 +1,264 @@
|
|||
.\" Generated by scdoc 1.11.2
|
||||
.\" Complete documentation for this program is not available as a GNU info page
|
||||
.ie \n(.g .ds Aq \(aq
|
||||
.el .ds Aq '
|
||||
.nh
|
||||
.ad l
|
||||
.\" Begin generated content:
|
||||
.TH "awl" "1" "2022-07-22"
|
||||
.PP
|
||||
.SH NAME
|
||||
awl - DNS lookup tool
|
||||
.PP
|
||||
.SH SYNOPSIS
|
||||
\fBawl\fR [ \fIOPTIONS\fR ] \fIname\fR [ \fI@server\fR ] [ \fItype\fR ]
|
||||
.br
|
||||
where
|
||||
.PP
|
||||
\fIname\fR is the query to make (\fBexample: froth.\&zone\fR)
|
||||
.br
|
||||
\fI@server\fR is the server to query (\fBexample: dns.\&froth.\&zone\fR)
|
||||
.br
|
||||
\fItype\fR is the DNS resource type (\fBexample: AAAA\fR)
|
||||
.PP
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
\fBawl\fR (\fBa\fRwls \fBw\fRant \fBl\fRicorice) is a simple tool designed to make DNS queries,
|
||||
much like the venerable \fIdig\fR(1).\& An awl is a tool used to make small holes,
|
||||
typically used in tannery (leatherworking).\&
|
||||
.PP
|
||||
\fBawl\fR is designed to be a more "modern" version of \fIdrill\fR(1) by including
|
||||
some more recent RFCs and output options.\& \fBawl\fR is still heavily
|
||||
Work-In-Progress so some features may get added or removed.\&
|
||||
.PP
|
||||
.SH OPTIONS
|
||||
.RS 4
|
||||
Dig-like +[no]flags are supported, see dig(1)
|
||||
.PP
|
||||
\fB-D\fR, \fB--dnssec\fR, \fB+dnssec\fR
|
||||
.br
|
||||
Enable DNSSEC.\& This needs to be manually enabled.\&
|
||||
.PP
|
||||
\fB-v\fR \fIvalue\fR
|
||||
.br
|
||||
Set verbosity (currently WIP)
|
||||
.PP
|
||||
\fB-V\fR
|
||||
.br
|
||||
Print the version and exit.\&
|
||||
.PP
|
||||
\fB-h\fR
|
||||
.br
|
||||
Show a "short" help message.\&
|
||||
.PP
|
||||
.RE
|
||||
.SS Query Options
|
||||
.RS 4
|
||||
\fB-4\fR
|
||||
.br
|
||||
Only make query over IPv4
|
||||
.PP
|
||||
\fB-6\fR
|
||||
.br
|
||||
Only make query over IPv6
|
||||
.PP
|
||||
\fB-p\fR, \fB--port\fR \fIport\fR
|
||||
.br
|
||||
Sets the port to query.\&
|
||||
.br
|
||||
|
||||
.br
|
||||
\fIDefault Ports\fR:
|
||||
.RS 4
|
||||
.PD 0
|
||||
.IP \(bu 4
|
||||
\fI53\fR for \fBUDP\fR and \fBTCP\fR
|
||||
.IP \(bu 4
|
||||
\fI853\fR for \fBTLS\fR and \fBQUIC\fR
|
||||
.IP \(bu 4
|
||||
\fI443\fR for \fBHTTPS\fR
|
||||
.PD
|
||||
.PP
|
||||
.RE
|
||||
\fB-q\fR, \fB--query\fR \fIdomain\fR
|
||||
.br
|
||||
Domain to query (eg.\& example.\&com)
|
||||
.PP
|
||||
\fB-c\fR, \fB--class\fR \fIclass\fR
|
||||
.br
|
||||
DNS class to query (eg.\& IN, CH)
|
||||
.PP
|
||||
\fB-t\fR, \fB--qType\fR \fItype\fR
|
||||
.br
|
||||
DNS type to query (eg.\& A, NS)
|
||||
.PP
|
||||
\fB--no-truncate\fR, \fB+ignore\fR
|
||||
.br
|
||||
Ignore UDP truncation (by default, awl \fIretries with TCP\fR)
|
||||
.PP
|
||||
\fB-t\fR, \fB--tcp\fR, \fB+tcp\fR, \fB+vc\fR
|
||||
.br
|
||||
Use TCP for the query (see \fIRFC 7766\fR)
|
||||
.PP
|
||||
\fB--dnscrypt\fR
|
||||
.br
|
||||
Use DNSCrypt
|
||||
.PP
|
||||
\fB-T\fR, \fB--tls\fR, \fB+tls\fR
|
||||
.br
|
||||
Use DNS-over-TLS, implies \fB--tcp\fR (see \fIRFC 7858\fR)
|
||||
.PP
|
||||
\fB-H\fR.\& \fB--https\fR, \fB+https\fR
|
||||
.br
|
||||
Use DNS-over-HTTPS (see \fIRFC 8484\fR)
|
||||
.PP
|
||||
\fB-Q\fR.\& \fB--quic\fR, \fB+quic\fR
|
||||
.br
|
||||
Use DNS-over-QUIC (see \fIRFC 9250\fR)
|
||||
.PP
|
||||
\fB-x\fR, \fB--reverse\fR
|
||||
.br
|
||||
Do a reverse lookup.\& Sets default \fItype\fR to PTR.\&
|
||||
.br
|
||||
\fBawl\fR automatically makes an IP or phone number canonical.\&
|
||||
.PP
|
||||
.RE
|
||||
.SS DNS Flags
|
||||
.PP
|
||||
.RS 4
|
||||
\fB--aa=[false]\fR, \fB+[no]aaflag\fR
|
||||
.br
|
||||
(Set, Unset) AA (Authoritative Answer) flag
|
||||
.PP
|
||||
\fB--ad=[false]\fR, \fB+[no]adflag\fR
|
||||
.br
|
||||
(Set, Unset) AD (Authenticated Data) flag
|
||||
.PP
|
||||
\fB--tc=[false]\fR, \fB+[no]tcflag\fR
|
||||
.br
|
||||
(Set, Unset) TC (TrunCated) flag
|
||||
.PP
|
||||
\fB-z=[false]\fR, \fB+[no]zflag\fR
|
||||
.br
|
||||
(Set, Unset) Z (Zero) flag
|
||||
.PP
|
||||
\fB--cd=[false]\fR, \fB+[no]cdflag\fR
|
||||
.br
|
||||
(Set, Unset) CD (Checking Disabled) flag
|
||||
.PP
|
||||
\fB--qr=[false]\fR, \fB+[no]qrflag\fR
|
||||
.br
|
||||
(Set, Unset) QR (QueRy) flag
|
||||
.PP
|
||||
\fB--rd=[true]\fR, \fB+[no]rdflag\fR
|
||||
.br
|
||||
(Set, Unset) RD (Recursion Desired) flag
|
||||
.PP
|
||||
\fB--ra=[false]\fR, \fB+[no]raflag\fR
|
||||
.br
|
||||
(Set, Unset) RA (Recursion Available) flag
|
||||
.PP
|
||||
.RE
|
||||
.SS Output Display
|
||||
.RS 4
|
||||
\fB--no-question\fR, \fB+noquestion\fR
|
||||
.br
|
||||
Do not display the Question section
|
||||
.PP
|
||||
\fB--no-answer\fR, \fB+noanswer\fR
|
||||
.br
|
||||
Do not display the Answer section
|
||||
.PP
|
||||
\fB--no-answer\fR, \fB+noanswer\fR
|
||||
.br
|
||||
Do not display the Answer section
|
||||
.PP
|
||||
\fB--no-authority\fR, \fB+noauthority\fR
|
||||
.br
|
||||
Do not display the Authority section
|
||||
.PP
|
||||
\fB--no-additional\fR, \fB+noadditional\fR
|
||||
.br
|
||||
Do not display the Additional section
|
||||
.PP
|
||||
\fB--no-statistics\fR, \fB+nostatistics\fR
|
||||
.br
|
||||
Do not display the Statistics (additional comments) section
|
||||
.PP
|
||||
.RE
|
||||
.SS Output Formats
|
||||
.RS 4
|
||||
\fB-j\fR, \fB--json\fR, \fB+json\fR
|
||||
.br
|
||||
Print the query results as JSON.\&
|
||||
.PP
|
||||
\fB-X\fR, \fB--xml\fR, \fB+xml\fR
|
||||
.br
|
||||
Print the query results as XML.\&
|
||||
.PP
|
||||
\fB-y\fR, \fB--yaml\fR, \fB+yaml\fR
|
||||
.br
|
||||
Print the query results as YAML.\&
|
||||
.PP
|
||||
\fB-s\fR, \fB--short\fR, \fB+short\fR
|
||||
.br
|
||||
Print just the results.\&
|
||||
.PP
|
||||
.RE
|
||||
.SH EXAMPLES
|
||||
.nf
|
||||
.RS 4
|
||||
awl grumbulon\&.xyz -j +cd
|
||||
.fi
|
||||
.RE
|
||||
Run a query of your local resolver for the A records of grumbulon.\&xyz, print
|
||||
them as JSON and disable DNSSEC verification.\&
|
||||
.PP
|
||||
.nf
|
||||
.RS 4
|
||||
awl +short example\&.com AAAA @1\&.1\&.1\&.1
|
||||
.fi
|
||||
.RE
|
||||
Query 1.\&1.\&1.\&1 for the AAAA records of example.\&com, print just the answers
|
||||
.PP
|
||||
.nf
|
||||
.RS 4
|
||||
awl -xT PTR 8\&.8\&.4\&.4 @dns\&.google
|
||||
.fi
|
||||
.RE
|
||||
Query dns.\&google over TLS for the PTR record to the IP address 8.\&8.\&4.\&4
|
||||
.PP
|
||||
.SH SEE ALSO
|
||||
.\" Generated by scdoc 1.11.2
|
||||
.\" Complete documentation for this program is not available as a GNU info page
|
||||
.ie \n(.g .ds Aq \(aq
|
||||
.el .ds Aq '
|
||||
.nh
|
||||
.ad l
|
||||
.\" Begin generated content:
|
||||
.TH "awl" "1" "2022-07-24"
|
||||
.P
|
||||
.SH NAME
|
||||
awl - DNS lookup tool
|
||||
.P
|
||||
.SH SYNOPSIS
|
||||
\fBawl\fR [ \fIOPTIONS\fR ] \fIname\fR [ \fI@server\fR ] [ \fItype\fR ]
|
||||
.br
|
||||
where
|
||||
.P
|
||||
\fIname\fR is the query to make (\fBexample: froth.\&zone\fR)
|
||||
.br
|
||||
\fI@server\fR is the server to query (\fBexample: dns.\&froth.\&zone\fR)
|
||||
.br
|
||||
\fItype\fR is the DNS resource type (\fBexample: AAAA\fR)
|
||||
.P
|
||||
.SH DESCRIPTION
|
||||
.P
|
||||
\fBawl\fR (\fBa\fRwls \fBw\fRant \fBl\fRicorice) is a simple tool designed to make DNS queries,
|
||||
much like the venerable \fIdig\fR(1).\& An awl is a tool used to make small holes,
|
||||
typically used in tannery (leatherworking).\&
|
||||
.P
|
||||
\fBawl\fR is designed to be a more "modern" version of \fIdrill\fR(1) by including
|
||||
some more recent RFCs and output options.\& \fBawl\fR is still heavily
|
||||
Work-In-Progress so some features may get added or removed.\&
|
||||
.P
|
||||
.SH OPTIONS
|
||||
.RS 4
|
||||
Dig-like +[no]flags are supported, see dig(1)
|
||||
.P
|
||||
\fB-D\fR, \fB--dnssec\fR, \fB+dnssec\fR
|
||||
.br
|
||||
Enable DNSSEC.\& This needs to be manually enabled.\&
|
||||
.P
|
||||
\fB-v\fR \fIvalue\fR
|
||||
.br
|
||||
Set verbosity (currently WIP)
|
||||
.P
|
||||
\fB-V\fR
|
||||
.br
|
||||
Print the version and exit.\&
|
||||
.P
|
||||
\fB-h\fR
|
||||
.br
|
||||
Show a "short" help message.\&
|
||||
.P
|
||||
.RE
|
||||
.SS Query Options
|
||||
.RS 4
|
||||
\fB-4\fR
|
||||
.br
|
||||
Only make query over IPv4
|
||||
.P
|
||||
\fB-6\fR
|
||||
.br
|
||||
Only make query over IPv6
|
||||
.P
|
||||
\fB-p\fR, \fB--port\fR \fIport\fR
|
||||
.br
|
||||
Sets the port to query.\&
|
||||
.br
|
||||
|
||||
.br
|
||||
\fIDefault Ports\fR:
|
||||
.RS 4
|
||||
.RS 4
|
||||
.ie n \{\
|
||||
\h'-04'\(bu\h'+03'\c
|
||||
.\}
|
||||
.el \{\
|
||||
.IP \(bu 4
|
||||
.\}
|
||||
\fI53\fR for \fBUDP\fR and \fBTCP\fR
|
||||
.RE
|
||||
.RS 4
|
||||
.ie n \{\
|
||||
\h'-04'\(bu\h'+03'\c
|
||||
.\}
|
||||
.el \{\
|
||||
.IP \(bu 4
|
||||
.\}
|
||||
\fI853\fR for \fBTLS\fR and \fBQUIC\fR
|
||||
.RE
|
||||
.RS 4
|
||||
.ie n \{\
|
||||
\h'-04'\(bu\h'+03'\c
|
||||
.\}
|
||||
.el \{\
|
||||
.IP \(bu 4
|
||||
.\}
|
||||
\fI443\fR for \fBHTTPS\fR
|
||||
|
||||
.RE
|
||||
.P
|
||||
.RE
|
||||
\fB-q\fR, \fB--query\fR \fIdomain\fR
|
||||
.br
|
||||
Domain to query (eg.\& example.\&com)
|
||||
.P
|
||||
\fB-c\fR, \fB--class\fR \fIclass\fR
|
||||
.br
|
||||
DNS class to query (eg.\& IN, CH)
|
||||
.P
|
||||
\fB-t\fR, \fB--qType\fR \fItype\fR
|
||||
.br
|
||||
DNS type to query (eg.\& A, NS)
|
||||
.P
|
||||
\fB--no-truncate\fR, \fB+ignore\fR
|
||||
.br
|
||||
Ignore UDP truncation (by default, awl \fIretries with TCP\fR)
|
||||
.P
|
||||
\fB--tcp\fR, \fB+tcp\fR, \fB+vc\fR
|
||||
.br
|
||||
Use TCP for the query (see \fIRFC 7766\fR)
|
||||
.P
|
||||
\fB--dnscrypt\fR, \fB+dnscrypt\fR
|
||||
.br
|
||||
Use DNSCrypt
|
||||
.P
|
||||
\fB-T\fR, \fB--tls\fR, \fB+tls\fR
|
||||
.br
|
||||
Use DNS-over-TLS, implies \fB--tcp\fR (see \fIRFC 7858\fR)
|
||||
.P
|
||||
\fB-H\fR.\& \fB--https\fR, \fB+https\fR
|
||||
.br
|
||||
Use DNS-over-HTTPS (see \fIRFC 8484\fR)
|
||||
.P
|
||||
\fB-Q\fR.\& \fB--quic\fR, \fB+quic\fR
|
||||
.br
|
||||
Use DNS-over-QUIC (see \fIRFC 9250\fR)
|
||||
.P
|
||||
\fB-x\fR, \fB--reverse\fR
|
||||
.br
|
||||
Do a reverse lookup.\& Sets default \fItype\fR to PTR.\&
|
||||
.br
|
||||
\fBawl\fR automatically makes an IP or phone number canonical.\&
|
||||
.P
|
||||
\fB--timeout\fR \fIseconds\fR, \fB+timeout=\fR\fIseconds\fR
|
||||
.br
|
||||
Set the timeout period.\& Floating point numbers are accepted.\&
|
||||
.br
|
||||
0.\&5 seconds is the minimum.\&
|
||||
.P
|
||||
\fB--retry\fR \fIint\fR, \fB+tries\fR=\fIint\fR, \fB+ retry\fR=\fIint\fR
|
||||
.br
|
||||
Set the number of retries.\&
|
||||
.br
|
||||
Retry is one more than tries, dig style
|
||||
.P
|
||||
.RE
|
||||
.SS DNS Flags
|
||||
.P
|
||||
.RS 4
|
||||
\fB--aa=[false]\fR, \fB+[no]aaflag\fR
|
||||
.br
|
||||
(Set, Unset) AA (Authoritative Answer) flag
|
||||
.P
|
||||
\fB--ad=[false]\fR, \fB+[no]adflag\fR
|
||||
.br
|
||||
(Set, Unset) AD (Authenticated Data) flag
|
||||
.P
|
||||
\fB--tc=[false]\fR, \fB+[no]tcflag\fR
|
||||
.br
|
||||
(Set, Unset) TC (TrunCated) flag
|
||||
.P
|
||||
\fB-z=[false]\fR, \fB+[no]zflag\fR
|
||||
.br
|
||||
(Set, Unset) Z (Zero) flag
|
||||
.P
|
||||
\fB--cd=[false]\fR, \fB+[no]cdflag\fR
|
||||
.br
|
||||
(Set, Unset) CD (Checking Disabled) flag
|
||||
.P
|
||||
\fB--qr=[false]\fR, \fB+[no]qrflag\fR
|
||||
.br
|
||||
(Set, Unset) QR (QueRy) flag
|
||||
.P
|
||||
\fB--rd=[true]\fR, \fB+[no]rdflag\fR
|
||||
.br
|
||||
(Set, Unset) RD (Recursion Desired) flag
|
||||
.P
|
||||
\fB--ra=[false]\fR, \fB+[no]raflag\fR
|
||||
.br
|
||||
(Set, Unset) RA (Recursion Available) flag
|
||||
.P
|
||||
.RE
|
||||
.SS Output Display
|
||||
.RS 4
|
||||
\fB--no-question\fR, \fB+noquestion\fR
|
||||
.br
|
||||
Do not display the Question section
|
||||
.P
|
||||
\fB--no-answer\fR, \fB+noanswer\fR
|
||||
.br
|
||||
Do not display the Answer section
|
||||
.P
|
||||
\fB--no-answer\fR, \fB+noanswer\fR
|
||||
.br
|
||||
Do not display the Answer section
|
||||
.P
|
||||
\fB--no-authority\fR, \fB+noauthority\fR
|
||||
.br
|
||||
Do not display the Authority section
|
||||
.P
|
||||
\fB--no-additional\fR, \fB+noadditional\fR
|
||||
.br
|
||||
Do not display the Additional section
|
||||
.P
|
||||
\fB--no-statistics\fR, \fB+nostats\fR
|
||||
.br
|
||||
Do not display the Statistics (additional comments) section
|
||||
.P
|
||||
.RE
|
||||
.SS Output Formats
|
||||
.RS 4
|
||||
\fB-j\fR, \fB--json\fR, \fB+json\fR
|
||||
.br
|
||||
Print the query results as JSON.\&
|
||||
.P
|
||||
\fB-X\fR, \fB--xml\fR, \fB+xml\fR
|
||||
.br
|
||||
Print the query results as XML.\&
|
||||
.P
|
||||
\fB-y\fR, \fB--yaml\fR, \fB+yaml\fR
|
||||
.br
|
||||
Print the query results as YAML.\&
|
||||
.P
|
||||
\fB-s\fR, \fB--short\fR, \fB+short\fR
|
||||
.br
|
||||
Print just the address of the answer.\&
|
||||
.P
|
||||
.RE
|
||||
.SH EXAMPLES
|
||||
.nf
|
||||
.RS 4
|
||||
awl grumbulon\&.xyz -j +cd
|
||||
.fi
|
||||
.RE
|
||||
Run a query of your local resolver for the A records of grumbulon.\&xyz, print
|
||||
them as JSON and disable DNSSEC verification.\&
|
||||
.P
|
||||
.nf
|
||||
.RS 4
|
||||
awl +short example\&.com AAAA @1\&.1\&.1\&.1
|
||||
.fi
|
||||
.RE
|
||||
Query 1.\&1.\&1.\&1 for the AAAA records of example.\&com, print just the answers
|
||||
.P
|
||||
.nf
|
||||
.RS 4
|
||||
awl -xT PTR 8\&.8\&.4\&.4 @dns\&.google
|
||||
.fi
|
||||
.RE
|
||||
Query dns.\&google over TLS for the PTR record to the IP address 8.\&8.\&4.\&4
|
||||
.P
|
||||
.SH SEE ALSO
|
||||
\fIdrill\fR(1), \fIdig\fR(1), the many DNS RFCs
|
11
doc/awl.1.md
11
doc/awl.1.md
|
@ -66,7 +66,7 @@ _Default Ports_:
|
|||
*--tcp*, *+tcp*, *+vc*++
|
||||
Use TCP for the query (see _RFC 7766_)
|
||||
|
||||
*--dnscrypt*++
|
||||
*--dnscrypt*, *+dnscrypt*++
|
||||
Use DNSCrypt
|
||||
|
||||
*-T*, *--tls*, *+tls*++
|
||||
|
@ -82,8 +82,13 @@ _Default Ports_:
|
|||
Do a reverse lookup. Sets default _type_ to PTR.++
|
||||
*awl* automatically makes an IP or phone number canonical.
|
||||
|
||||
*--timeout* _seconds_
|
||||
Set the timeout period. Floating point numbers are accepted.
|
||||
*--timeout* _seconds_, *+timeout=*_seconds_++
|
||||
Set the timeout period. Floating point numbers are accepted.++
|
||||
0.5 seconds is the minimum.
|
||||
|
||||
*--retry* _int_, *+tries*=_int_, *+ retry*=_int_++
|
||||
Set the number of retries.++
|
||||
Retry is one more than tries, dig style
|
||||
|
||||
## DNS Flags
|
||||
|
||||
|
|
|
@ -21,4 +21,5 @@ type Request struct {
|
|||
Class uint16 `json:"class"` // DNS Class
|
||||
Name string `json:"name"` // The domain name to make a DNS request for
|
||||
Timeout time.Duration // The maximum timeout
|
||||
Retries int // Number of queries to retry
|
||||
}
|
||||
|
|
|
@ -133,12 +133,12 @@ func (l *Logger) Info(v ...any) {
|
|||
l.Println(InfoLevel, v...)
|
||||
}
|
||||
|
||||
// Call print directly with Error level
|
||||
func (l *Logger) Error(v ...any) {
|
||||
// Call print directly with Warn level
|
||||
func (l *Logger) Warn(v ...any) {
|
||||
l.Println(WarnLevel, v...)
|
||||
}
|
||||
|
||||
// Call print directly with Fatal level
|
||||
func (l *Logger) Fatal(v ...any) {
|
||||
// Call print directly with Error level
|
||||
func (l *Logger) Error(v ...any) {
|
||||
l.Println(ErrLevel, v...)
|
||||
}
|
||||
|
|
25
main.go
25
main.go
|
@ -13,6 +13,7 @@ import (
|
|||
"time"
|
||||
|
||||
"git.froth.zone/sam/awl/cli"
|
||||
"git.froth.zone/sam/awl/internal/helpers"
|
||||
"git.froth.zone/sam/awl/query"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
|
@ -27,12 +28,24 @@ func main() {
|
|||
if errors.Is(err, cli.ErrNotError) || strings.Contains(err.Error(), "help requested") {
|
||||
os.Exit(0)
|
||||
}
|
||||
opts.Logger.Fatal(err)
|
||||
opts.Logger.Error(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
resp, err := query.CreateQuery(opts)
|
||||
var resp helpers.Response
|
||||
|
||||
// Retry queries if a query fails
|
||||
for i := 0; i < opts.Request.Retries; i++ {
|
||||
resp, err = query.CreateQuery(opts)
|
||||
if err == nil {
|
||||
break
|
||||
} else {
|
||||
opts.Logger.Warn("Retrying")
|
||||
}
|
||||
}
|
||||
|
||||
// Query failed, make it fail
|
||||
if err != nil {
|
||||
opts.Logger.Fatal(err)
|
||||
opts.Logger.Error(err)
|
||||
os.Exit(9)
|
||||
}
|
||||
switch {
|
||||
|
@ -40,7 +53,7 @@ func main() {
|
|||
opts.Logger.Info("Printing as JSON")
|
||||
json, err := json.MarshalIndent(resp.DNS, "", " ")
|
||||
if err != nil {
|
||||
opts.Logger.Fatal(err)
|
||||
opts.Logger.Error(err)
|
||||
os.Exit(10)
|
||||
}
|
||||
fmt.Println(string(json))
|
||||
|
@ -48,7 +61,7 @@ func main() {
|
|||
opts.Logger.Info("Printing as XML")
|
||||
xml, err := xml.MarshalIndent(resp.DNS, "", " ")
|
||||
if err != nil {
|
||||
opts.Logger.Fatal(err)
|
||||
opts.Logger.Error(err)
|
||||
os.Exit(10)
|
||||
}
|
||||
fmt.Println(string(xml))
|
||||
|
@ -56,7 +69,7 @@ func main() {
|
|||
opts.Logger.Info("Printing as YAML")
|
||||
yaml, err := yaml.Marshal(resp.DNS)
|
||||
if err != nil {
|
||||
opts.Logger.Fatal(err)
|
||||
opts.Logger.Error(err)
|
||||
os.Exit(10)
|
||||
}
|
||||
fmt.Println(string(yaml))
|
||||
|
|
Loading…
Reference in a new issue