API work #94

Merged
sam merged 6 commits from idk-what-to-name-this-hope-this-works into master 2022-09-15 11:02:43 +00:00
18 changed files with 572 additions and 417 deletions
Showing only changes of commit b9abedfca2 - Show all commits

12
.editorconfig Normal file
View file

@ -0,0 +1,12 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = false
insert_final_newline = false

View file

@ -116,7 +116,6 @@ func ParseCLI(version string) (util.Options, error) {
opts := util.Options{
Logger: util.InitLogger(*verbosity),
Port: *port,
IPv4: *ipv4,
IPv6: *ipv6,
Short: *short,
@ -128,29 +127,29 @@ func ParseCLI(version string) (util.Options, error) {
HTTPS: *https,
QUIC: *quic,
Truncate: *truncate,
ShowQuery: false,
AA: *aaflag,
AD: *adflag,
TC: *tcflag,
Z: *zflag,
CD: *cdflag,
QR: *qrflag,
RD: *rdflag,
RA: *raflag,
Reverse: *reverse,
HumanTTL: false,
ShowTTL: true,
JSON: *json,
XML: *xml,
YAML: *yaml,
HeaderFlags: util.HeaderFlags{
AA: *aaflag,
AD: *adflag,
TC: *tcflag,
Z: *zflag,
CD: *cdflag,
QR: *qrflag,
RD: *rdflag,
RA: *raflag,
},
Request: util.Request{
Type: dns.StringToType[strings.ToUpper(*qType)],
Class: dns.StringToClass[strings.ToUpper(*class)],
Name: *query,
Timeout: time.Duration(*timeout * float32(time.Second)),
Retries: *retry,
Port: *port,
},
Display: util.Displays{
Display: util.Display{
Comments: !*noC,
Question: !*noQ,
Opt: !*noOpt,
@ -158,6 +157,9 @@ func ParseCLI(version string) (util.Options, error) {
Authority: !*noAuth,
Additional: !*noAdd,
Statistics: !*noStats,
HumanTTL: false,
ShowQuery: false,
TTL: true,
},
EDNS: util.EDNS{
EnableEDNS: !*edns,
@ -199,15 +201,15 @@ func ParseCLI(version string) (util.Options, error) {
opts.Logger.Info("Dig/Drill flags parsed")
opts.Logger.Debug(fmt.Sprintf("%+v", opts))
if opts.Port == 0 {
if opts.Request.Port == 0 {
if opts.TLS || opts.QUIC {
opts.Port = 853
opts.Request.Port = 853
} else {
opts.Port = 53
opts.Request.Port = 53
}
}
opts.Logger.Info("Port set to", opts.Port)
opts.Logger.Info("Port set to", opts.Request.Port)
// Set timeout to 0.5 seconds if set below 0.5
if opts.Request.Timeout < (time.Second / 2) {
@ -218,6 +220,9 @@ func ParseCLI(version string) (util.Options, error) {
opts.Request.Retries = 0
}
opts.Logger.Info("Options fully populated")
opts.Logger.Debug(fmt.Sprintf("%+v", opts))
return opts, nil
}

View file

@ -18,7 +18,7 @@ func TestEmpty(t *testing.T) {
opts, err := cli.ParseCLI("TEST")
assert.NilError(t, err)
assert.Equal(t, opts.Port, 53)
assert.Equal(t, opts.Request.Port, 53)
assert.Assert(t, opts.IPv4)
os.Args = args
@ -31,7 +31,7 @@ func TestTLSPort(t *testing.T) {
opts, err := cli.ParseCLI("TEST")
assert.NilError(t, err)
assert.Equal(t, opts.Port, 853)
assert.Equal(t, opts.Request.Port, 853)
os.Args = args
}

View file

@ -45,13 +45,13 @@ func ParseDig(arg string, opts *util.Options) error {
// End DNS query flags
case "qr":
opts.ShowQuery = isNo
opts.Display.ShowQuery = isNo
case "ttlunits":
opts.HumanTTL = isNo
opts.Display.HumanTTL = isNo
case "ttl", "ttlid":
opts.ShowTTL = isNo
opts.Display.TTL = isNo
case "class":
opts.ShowClass = isNo
opts.Display.ShowClass = isNo
// EDNS queries
case "dnssec":

17
go.mod
View file

@ -9,6 +9,7 @@ require (
github.com/miekg/dns v1.1.50
github.com/stefansundin/go-zflag v1.1.1
golang.org/x/net v0.0.0-20220909164309-bea034e7d591
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64
gopkg.in/yaml.v3 v3.0.1
gotest.tools/v3 v3.3.0
)
@ -18,22 +19,18 @@ require (
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 // indirect
github.com/ameshkov/dnsstamps v1.0.3 // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/marten-seemann/qtls-go1-19 v0.1.0 // indirect
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 // indirect
)
require (
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/marten-seemann/qtls-go1-18 v0.1.2 // indirect
github.com/marten-seemann/qtls-go1-19 v0.1.0 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect
github.com/onsi/ginkgo v1.16.4 // indirect
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d // indirect
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.12 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect

28
go.sum
View file

@ -15,9 +15,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/dchest/uniuri v0.0.0-20200228104902-7aecb25e1fe5 h1:RAV05c0xOkJ3dZGS0JFybxFKZ2WMLabgx3uXnd7rpGs=
github.com/dchest/uniuri v0.0.0-20200228104902-7aecb25e1fe5/go.mod h1:GgB8SF9nRG+GqaDtLcwJZsQFhcogVCJ79j4EdT0c2V4=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
@ -57,8 +56,8 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
@ -77,12 +76,10 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM=
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 h1:tnebWN09GYg9OLPss1KXj8txwZc6X6uMr6VFdcGNbHw=
golang.org/x/exp v0.0.0-20220827204233-334a2380cb91/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E=
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d h1:3qF+Z8Hkrw9sOhrFHti9TlB1Hkac1x+DNRkv0XQiFjo=
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
@ -94,8 +91,6 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220907135653-1e95f45603a7 h1:1WGATo9HAhkWMbfyuVU0tEFP88OIkUvwaHFveQPvzCQ=
golang.org/x/net v0.0.0-20220907135653-1e95f45603a7/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI=
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -118,13 +113,8 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220907062415-87db552b00fd h1:AZeIEzg+8RCELJYq8w+ODLVxFgLMMigSwO/ffKPEd9U=
golang.org/x/sys v0.0.0-20220907062415-87db552b00fd/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956 h1:XeJjHH1KiLpKGb6lvMiksZ9l0fVUh+AmGcm0nOMEBOY=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2 h1:wM1k/lXfpc5HdkJJyW9GELpd8ERGdnh8sMGL6Gzq3Ho=
golang.org/x/sys v0.0.0-20220909162455-aba9fc2a8ff2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 h1:UiNENfZ8gDvpiWw7IpOMQ27spWmThO1RwwdQVbJahJM=
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=

View file

@ -139,17 +139,37 @@ func (l *Logger) Debug(v ...any) {
l.Println(DebugLevel, v...)
}
// Debugf calls print after formatting the string with Debug level.
func (l *Logger) Debugf(format string, v ...any) {
l.Println(ErrLevel, fmt.Sprintf(format, v...))
}
// Info calls print directly with Info level.
func (l *Logger) Info(v ...any) {
l.Println(InfoLevel, v...)
}
// Infof calls print after formatting the string with Info level.
func (l *Logger) Infof(format string, v ...any) {
l.Println(ErrLevel, fmt.Sprintf(format, v...))
}
// Warn calls print directly with Warn level.
func (l *Logger) Warn(v ...any) {
l.Println(WarnLevel, v...)
}
// Warnf calls print after formatting the string with Warn level.
func (l *Logger) Warnf(format string, v ...any) {
l.Println(WarnLevel, fmt.Sprintf(format, v...))
}
// Error calls print directly with Error level.
func (l *Logger) Error(v ...any) {
l.Println(ErrLevel, v...)
}
// Errorf calls print after formatting the string with Error level.
func (l *Logger) Errorf(format string, v ...any) {
l.Println(ErrLevel, fmt.Sprintf(format, v...))
}

View file

@ -52,6 +52,7 @@ func TestLogger(t *testing.T) {
case 0:
fn := func() {
logger.Error("Test", "E")
logger.Errorf("%s", "Test")
}
var buffer bytes.Buffer
@ -62,6 +63,7 @@ func TestLogger(t *testing.T) {
case 1:
fn := func() {
logger.Warn("Test")
logger.Warnf("%s", "Test")
}
var buffer bytes.Buffer
@ -72,6 +74,7 @@ func TestLogger(t *testing.T) {
case 2:
fn := func() {
logger.Info("Test")
logger.Infof("%s", "Test")
}
var buffer bytes.Buffer
@ -83,6 +86,8 @@ func TestLogger(t *testing.T) {
fn := func() {
logger.Debug("Test")
logger.Debug("Test 2")
logger.Debugf("%s", "Test")
logger.Debugf("%s %d", "Test", 2)
}
var buffer bytes.Buffer

View file

@ -22,8 +22,7 @@ func TestQuic(t *testing.T) {
opts := util.Options{
QUIC: true,
Logger: util.InitLogger(0),
Port: 853,
Request: util.Request{Server: "dns.adguard.com"},
Request: util.Request{Server: "dns.adguard.com", Port: 853},
}
testCase := util.Request{Server: "dns.//./,,adguard.com", Type: dns.TypeA, Name: "git.froth.zone"}
testCase2 := util.Request{Server: "dns.adguard.com", Type: dns.TypeA, Name: "git.froth.zone"}
@ -54,7 +53,7 @@ func TestQuic(t *testing.T) {
resolver, err := query.LoadResolver(opts)
assert.NilError(t, err)
testCase2.Server = net.JoinHostPort(testCase2.Server, strconv.Itoa(opts.Port))
testCase2.Server = net.JoinHostPort(testCase2.Server, strconv.Itoa(opts.Request.Port))
// if the domain is not canonical, make it canonical
if !strings.HasSuffix(testCase2.Name, ".") {
@ -78,8 +77,7 @@ func TestInvalidQuic(t *testing.T) {
opts := util.Options{
QUIC: true,
Logger: util.InitLogger(0),
Port: 853,
Request: util.Request{Server: "example.com", Type: dns.TypeA, Name: "git.froth.zone", Timeout: 10 * time.Millisecond},
Request: util.Request{Server: "example.com", Port: 853, Type: dns.TypeA, Name: "git.froth.zone", Timeout: 10 * time.Millisecond},
}
resolver, err := query.LoadResolver(opts)
assert.NilError(t, err)

View file

@ -17,9 +17,9 @@ func TestResolve(t *testing.T) {
opts := util.Options{
Logger: util.InitLogger(0),
Port: 53,
Request: util.Request{
Server: "8.8.4.1",
Port: 53,
Type: dns.TypeA,
Name: "example.com.",
Timeout: time.Second / 2,
@ -42,9 +42,9 @@ func TestTruncate(t *testing.T) {
opts := util.Options{
Logger: util.InitLogger(0),
IPv4: true,
Port: 5301,
Request: util.Request{
Server: "madns.binarystar.systems",
Port: 5301,
Type: dns.TypeTXT,
Name: "limit.txt.example.",
},
@ -70,9 +70,10 @@ func TestResolveAgain(t *testing.T) {
util.Options{
Logger: util.InitLogger(0),
TCP: true,
Port: 53,
Request: util.Request{
Server: "8.8.4.4",
Port: 53,
Type: dns.TypeA,
Name: "example.com.",
},
@ -81,9 +82,9 @@ func TestResolveAgain(t *testing.T) {
{
util.Options{
Logger: util.InitLogger(0),
Port: 53,
Request: util.Request{
Server: "8.8.4.4",
Port: 53,
Type: dns.TypeAAAA,
Name: "example.com.",
},
@ -93,9 +94,9 @@ func TestResolveAgain(t *testing.T) {
util.Options{
Logger: util.InitLogger(0),
TLS: true,
Port: 853,
Request: util.Request{
Server: "dns.google",
Port: 853,
Type: dns.TypeAAAA,
Name: "example.com.",
},

View file

@ -55,8 +55,21 @@ func PrintSpecial(msg *dns.Msg, opts util.Options) (string, error) {
func MakePrintable(msg *dns.Msg, opts util.Options) (*Message, error) {
var err error
// The things I do for compatibility
ret := Message{
Header: msg.MsgHdr,
Header: Header{
ID: msg.Id,
Response: msg.Response,
Opcode: dns.OpcodeToString[msg.Opcode],
Authoritative: msg.Authoritative,
Truncated: msg.Truncated,
RecursionDesired: msg.RecursionDesired,
RecursionAvailable: msg.RecursionAvailable,
Zero: msg.Zero,
AuthenticatedData: msg.AuthenticatedData,
CheckingDisabled: msg.CheckingDisabled,
Status: dns.RcodeToString[msg.Rcode],
},
}
for _, question := range msg.Question {
@ -85,8 +98,8 @@ func MakePrintable(msg *dns.Msg, opts util.Options) (*Message, error) {
name string
)
if opts.ShowTTL {
if opts.HumanTTL {
if opts.Display.TTL {
if opts.Display.HumanTTL {
ttl = (time.Duration(answer.Header().Ttl) * time.Second).String()
} else {
ttl = strconv.Itoa(int(answer.Header().Ttl))
@ -122,8 +135,8 @@ func MakePrintable(msg *dns.Msg, opts util.Options) (*Message, error) {
name string
)
if opts.ShowTTL {
if opts.HumanTTL {
if opts.Display.TTL {
if opts.Display.HumanTTL {
ttl = (time.Duration(ns.Header().Ttl) * time.Second).String()
} else {
ttl = strconv.Itoa(int(ns.Header().Ttl))
@ -139,7 +152,7 @@ func MakePrintable(msg *dns.Msg, opts util.Options) (*Message, error) {
name = ns.Header().Name
}
ret.Ns = append(ret.Ns, Answer{
ret.Authority = append(ret.Authority, Answer{
RRHeader: RRHeader{
Name: name,
Type: dns.TypeToString[ns.Header().Rrtype],
@ -162,8 +175,8 @@ func MakePrintable(msg *dns.Msg, opts util.Options) (*Message, error) {
name string
)
if opts.ShowTTL {
if opts.HumanTTL {
if opts.Display.TTL {
if opts.Display.HumanTTL {
ttl = (time.Duration(additional.Header().Ttl) * time.Second).String()
} else {
ttl = strconv.Itoa(int(additional.Header().Ttl))

View file

@ -16,15 +16,16 @@ func TestRealPrint(t *testing.T) {
opts := []util.Options{
{
Logger: util.InitLogger(0),
Port: 53,
TCP: true,
ShowQuery: true,
RD: true,
ShowTTL: true,
HumanTTL: true,
JSON: true,
Display: util.Displays{
Logger: util.InitLogger(0),
TCP: true,
HeaderFlags: util.HeaderFlags{
RD: true,
},
JSON: true,
Display: util.Display{
Comments: true,
Question: true,
Answer: true,
@ -32,9 +33,13 @@ func TestRealPrint(t *testing.T) {
Additional: true,
Statistics: true,
UcodeTranslate: true,
TTL: true,
HumanTTL: true,
ShowQuery: true,
},
Request: util.Request{
Server: "a.gtld-servers.net",
Port: 53,
Type: dns.StringToType["NS"],
Class: 1,
Name: "google.com.",
@ -44,17 +49,18 @@ func TestRealPrint(t *testing.T) {
},
},
{
Logger: util.InitLogger(0),
Port: 53,
TCP: true,
ShowQuery: true,
RD: true,
Logger: util.InitLogger(0),
TCP: true,
HeaderFlags: util.HeaderFlags{
RD: true,
},
Verbosity: 0,
ShowTTL: true,
Short: true,
Identify: true,
YAML: false,
Display: util.Displays{
Short: true,
Identify: true,
YAML: false,
Display: util.Display{
Comments: true,
Question: true,
Answer: true,
@ -62,9 +68,12 @@ func TestRealPrint(t *testing.T) {
Additional: true,
Statistics: true,
UcodeTranslate: true,
TTL: true,
ShowQuery: true,
},
Request: util.Request{
Server: "ns1.google.com",
Port: 53,
Type: dns.StringToType["NS"],
Class: 1,
Name: "google.com.",
@ -76,16 +85,14 @@ func TestRealPrint(t *testing.T) {
},
},
{
Logger: util.InitLogger(0),
Port: 53,
HTTPS: true,
ShowQuery: true,
RD: true,
ShowTTL: true,
HumanTTL: true,
Identify: true,
XML: true,
Display: util.Displays{
Logger: util.InitLogger(0),
HTTPS: true,
HeaderFlags: util.HeaderFlags{
RD: true,
},
Identify: true,
XML: true,
Display: util.Display{
Comments: true,
Question: true,
Answer: true,
@ -93,9 +100,13 @@ func TestRealPrint(t *testing.T) {
Additional: true,
Statistics: true,
UcodeTranslate: false,
TTL: true,
HumanTTL: true,
ShowQuery: true,
},
Request: util.Request{
Server: "https://dns.froth.zone/dns-query",
Port: 443,
Type: dns.StringToType["NS"],
Class: 1,
Name: "freecumextremist.com.",
@ -108,14 +119,13 @@ func TestRealPrint(t *testing.T) {
},
},
{
Logger: util.InitLogger(0),
Port: 853,
TLS: true,
ShowQuery: true,
RD: true,
Logger: util.InitLogger(0),
TLS: true,
HeaderFlags: util.HeaderFlags{
RD: true,
},
Verbosity: 0,
ShowTTL: false,
Display: util.Displays{
Display: util.Display{
Comments: true,
Question: true,
Answer: true,
@ -123,25 +133,29 @@ func TestRealPrint(t *testing.T) {
Additional: true,
Statistics: true,
UcodeTranslate: true,
TTL: false,
ShowQuery: true,
},
Request: util.Request{
Server: "dns.google",
Port: 853,
Type: dns.StringToType["NS"],
Class: 1,
Name: "freecumextremist.com.",
},
},
{
Logger: util.InitLogger(0),
Port: 53,
TCP: true,
ShowQuery: true,
AA: true,
RD: true,
Logger: util.InitLogger(0),
TCP: true,
HeaderFlags: util.HeaderFlags{
AA: true,
RD: true,
},
Verbosity: 0,
ShowTTL: true,
YAML: true,
Display: util.Displays{
YAML: true,
Display: util.Display{
Comments: true,
Question: true,
Answer: true,
@ -149,9 +163,12 @@ func TestRealPrint(t *testing.T) {
Additional: true,
Statistics: true,
UcodeTranslate: false,
TTL: true,
ShowQuery: true,
},
Request: util.Request{
Server: "rin.froth.zone",
Port: 53,
Type: dns.StringToType["A"],
Class: 1,
Name: "froth.zone.",

View file

@ -5,10 +5,13 @@ package query
import (
"fmt"
"strconv"
"strings"
"time"
"git.froth.zone/sam/awl/util"
"github.com/dchest/uniuri"
"github.com/miekg/dns"
"golang.org/x/net/idna"
)
const (
@ -16,6 +19,202 @@ const (
udp = "udp"
)
// ToString turns the response into something that looks a lot like dig
//
// Much of this is taken from https://github.com/miekg/dns/blob/master/msg.go#L900
func ToString(res util.Response, opts util.Options) (string, error) {
if res.DNS == nil {
return "<nil> MsgHdr", errNoMessage
}
var (
s string
opt *dns.OPT
)
if !opts.Short {
if opts.Display.Comments {
s += res.DNS.MsgHdr.String() + " "
s += "QUERY: " + strconv.Itoa(len(res.DNS.Question)) + ", "
s += "ANSWER: " + strconv.Itoa(len(res.DNS.Answer)) + ", "
s += "AUTHORITY: " + strconv.Itoa(len(res.DNS.Ns)) + ", "
s += "ADDITIONAL: " + strconv.Itoa(len(res.DNS.Extra)) + "\n"
opt = res.DNS.IsEdns0()
if opt != nil && opts.Display.Opt {
// OPT PSEUDOSECTION
s += opt.String() + "\n"
}
}
if opts.Display.Question {
if len(res.DNS.Question) > 0 {
if opts.Display.Comments {
s += "\n;; QUESTION SECTION:\n"
}
for _, r := range res.DNS.Question {
str, err := stringParse(r.String(), false, opts)
if err != nil {
return "", fmt.Errorf("%w", err)
}
s += str + "\n"
}
}
}
if opts.Display.Answer {
if len(res.DNS.Answer) > 0 {
if opts.Display.Comments {
s += "\n;; ANSWER SECTION:\n"
}
for _, r := range res.DNS.Answer {
if r != nil {
str, err := stringParse(r.String(), true, opts)
if err != nil {
return "", fmt.Errorf("%w", err)
}
s += str + "\n"
}
}
}
}
if opts.Display.Authority {
if len(res.DNS.Ns) > 0 {
if opts.Display.Comments {
s += "\n;; AUTHORITY SECTION:\n"
}
for _, r := range res.DNS.Ns {
if r != nil {
str, err := stringParse(r.String(), true, opts)
if err != nil {
return "", fmt.Errorf("%w", err)
}
s += str + "\n"
}
}
}
}
if opts.Display.Additional {
if len(res.DNS.Extra) > 0 && (opt == nil || len(res.DNS.Extra) > 1) {
if opts.Display.Comments {
s += "\n;; ADDITIONAL SECTION:\n"
}
for _, r := range res.DNS.Extra {
if r != nil && r.Header().Rrtype != dns.TypeOPT {
str, err := stringParse(r.String(), true, opts)
if err != nil {
return "", fmt.Errorf("%w", err)
}
s += str + "\n"
}
}
}
}
if opts.Display.Statistics {
s += "\n;; Query time: " + res.RTT.String()
// Add extra information to server string
var extra string
switch {
case opts.TCP:
extra = ":" + strconv.Itoa(opts.Request.Port) + " (TCP)"
case opts.TLS:
extra = ":" + strconv.Itoa(opts.Request.Port) + " (TLS)"
case opts.HTTPS, opts.DNSCrypt:
extra = ""
case opts.QUIC:
extra = ":" + strconv.Itoa(opts.Request.Port) + " (QUIC)"
default:
extra = ":" + strconv.Itoa(opts.Request.Port) + " (UDP)"
}
s += "\n;; SERVER: " + opts.Request.Server + extra
s += "\n;; WHEN: " + time.Now().Format(time.RFC1123Z)
s += "\n;; MSG SIZE rcvd: " + strconv.Itoa(res.DNS.Len()) + "\n"
}
} else {
// Print just the responses, nothing else
for i, resp := range res.DNS.Answer {
temp := strings.Split(resp.String(), "\t")
s += temp[len(temp)-1]
if opts.Identify {
s += " from server " + opts.Request.Server + " in " + res.RTT.String()
}
// Don't print newline on last line
if i != len(res.DNS.Answer)-1 {
s += "\n"
}
}
}
return s, nil
}
// stringParse edits the raw responses to user requests.
func stringParse(str string, isAns bool, opts util.Options) (string, error) {
split := strings.Split(str, "\t")
// Make edits if so requested
// TODO: make less ew?
// This exists because the question section should be left alone EXCEPT for punycode.
if isAns {
if !opts.Display.TTL {
// Remove from existence
split = append(split[:1], split[2:]...)
}
if !opts.Display.ShowClass {
// Position depends on if the TTL is there or not.
if opts.Display.TTL {
split = append(split[:2], split[3:]...)
} else {
split = append(split[:1], split[2:]...)
}
}
if opts.Display.TTL && opts.Display.HumanTTL {
ttl, _ := strconv.Atoi(split[1])
split[1] = (time.Duration(ttl) * time.Second).String()
}
}
if opts.Display.UcodeTranslate {
var (
err error
semi string
)
if strings.HasPrefix(split[0], ";") {
split[0] = strings.TrimPrefix(split[0], ";")
semi = ";"
}
split[0], err = idna.ToUnicode(split[0])
if err != nil {
return "", fmt.Errorf("punycode: %w", err)
}
split[0] = semi + split[0]
}
return strings.Join(split, "\t"), nil
}
// CreateQuery creates a DNS query from the options given.
// It sets query flags and EDNS flags from the respective options.
func CreateQuery(opts util.Options) (util.Response, error) {
@ -102,7 +301,7 @@ func CreateQuery(opts util.Options) (util.Response, error) {
opts.Logger.Debug(req)
if !opts.Short {
if opts.ShowQuery {
if opts.Display.ShowQuery {
opts.Logger.Info("Printing constructed query")
var (
@ -133,7 +332,7 @@ func CreateQuery(opts util.Options) (util.Response, error) {
fmt.Println(str)
opts.ShowQuery = false
opts.Display.ShowQuery = false
}
}

View file

@ -16,18 +16,20 @@ func TestCreateQ(t *testing.T) {
in := []util.Options{
{
Logger: util.InitLogger(0),
Port: 53,
Z: true,
ShowQuery: true,
YAML: true,
Logger: util.InitLogger(0),
HeaderFlags: util.HeaderFlags{
Z: true,
},
YAML: true,
Request: util.Request{
Server: "8.8.4.4",
Port: 53,
Type: dns.TypeA,
Name: "example.com.",
},
Display: util.Displays{
Display: util.Display{
Comments: true,
Question: true,
Opt: true,
@ -35,6 +37,7 @@ func TestCreateQ(t *testing.T) {
Authority: true,
Additional: true,
Statistics: true,
ShowQuery: true,
},
EDNS: util.EDNS{
ZFlag: 1,
@ -50,18 +53,19 @@ func TestCreateQ(t *testing.T) {
},
},
{
Logger: util.InitLogger(0),
Port: 53,
Z: true,
ShowQuery: true,
XML: true,
Logger: util.InitLogger(0),
HeaderFlags: util.HeaderFlags{
Z: true,
},
XML: true,
Request: util.Request{
Server: "8.8.4.4",
Port: 53,
Type: dns.TypeA,
Name: "example.com.",
},
Display: util.Displays{
Display: util.Display{
Comments: true,
Question: true,
Opt: true,
@ -70,22 +74,21 @@ func TestCreateQ(t *testing.T) {
Additional: true,
Statistics: true,
UcodeTranslate: true,
ShowQuery: true,
},
},
{
Logger: util.InitLogger(0),
Port: 853,
// Z: true,
ShowQuery: true,
JSON: true,
QUIC: true,
JSON: true,
QUIC: true,
Request: util.Request{
Server: "dns.adguard.com",
Port: 853,
Type: dns.TypeA,
Name: "example.com.",
},
Display: util.Displays{
Display: util.Display{
Comments: true,
Question: true,
Opt: true,
@ -93,6 +96,7 @@ func TestCreateQ(t *testing.T) {
Authority: true,
Additional: true,
Statistics: true,
ShowQuery: true,
},
EDNS: util.EDNS{
EnableEDNS: true,

View file

@ -31,7 +31,7 @@ func LoadResolver(opts util.Options) (Resolver, error) {
}, nil
case opts.QUIC:
opts.Logger.Info("loading DNS-over-QUIC resolver")
opts.Request.Server = net.JoinHostPort(opts.Request.Server, strconv.Itoa(opts.Port))
opts.Request.Server = net.JoinHostPort(opts.Request.Server, strconv.Itoa(opts.Request.Port))
return &QUICResolver{
opts: opts,
@ -48,7 +48,7 @@ func LoadResolver(opts util.Options) (Resolver, error) {
}, nil
default:
opts.Logger.Info("loading standard/DNS-over-TLS resolver")
opts.Request.Server = net.JoinHostPort(opts.Request.Server, strconv.Itoa(opts.Port))
opts.Request.Server = net.JoinHostPort(opts.Request.Server, strconv.Itoa(opts.Request.Port))
return &StandardResolver{
opts: opts,

View file

@ -4,48 +4,61 @@ package query
import (
"errors"
"fmt"
"strconv"
"strings"
"time"
"git.froth.zone/sam/awl/util"
"github.com/miekg/dns"
"golang.org/x/net/idna"
)
// Message is for overall DNS responses.
//
//nolint:govet // Better output is worth 32 bytes.
//nolint:govet // Better looking output is worth a few bytes.
type Message struct {
Header dns.MsgHdr `json:"header,omitempty" xml:"header,omitempty" yaml:",omitempty"`
Opt []Opts `json:"opt,omitempty" xml:"opt,omitempty" yaml:"opt,omitempty"`
Question []Question `json:"question,omitempty" xml:"question,omitempty" yaml:",omitempty"`
Answer []Answer `json:"answer,omitempty" xml:"answer,omitempty" yaml:",omitempty"`
Ns []Answer `json:"ns,omitempty" xml:"ns,omitempty" yaml:",omitempty"`
Additional []Answer `json:"additional,omitempty" xml:"additional,omitempty" yaml:",omitempty"`
// Header section
Header Header `json:"header,omitempty" xml:"header,omitempty" yaml:"header,omitempty"`
// Opt Pseudosection
Opt []Opts `json:"opt,omitempty" xml:"opt,omitempty" yaml:"opt,omitempty"`
// Question Section
Question []Question `json:"question,omitempty" xml:"question,omitempty" yaml:"question,omitempty"`
// Answer Section
Answer []Answer `json:"answer,omitempty" xml:"answer,omitempty" yaml:"answer,omitempty"`
// Authority Section
Authority []Answer `json:"authority,omitempty" xml:"authority,omitempty" yaml:"authority,omitempty"`
// Additional Section
Additional []Answer `json:"additional,omitempty" xml:"additional,omitempty" yaml:"additional,omitempty"`
}
// Header is the header.
type Header struct {
Opcode string `json:"opcode," xml:"opcode," yaml:"opcode"`
Status string `json:"status," xml:"status," yaml:"status"`
ID uint16 `json:"id," xml:"id," yaml:"id"`
Response bool `json:"response," xml:"response," yaml:"response"`
Authoritative bool `json:"authoritative," xml:"authoritative," yaml:"authoritative"`
Truncated bool `json:"truncated," xml:"truncated," yaml:"truncated"`
RecursionDesired bool `json:"recursionDesired," xml:"recursionDesired," yaml:"recursionDesired"`
RecursionAvailable bool `json:"recursionAvailable," xml:"recursionAvailable," yaml:"recursionAvailable"`
Zero bool `json:"zero," xml:"zero," yaml:"zero"`
AuthenticatedData bool `json:"authenticatedData," xml:"authenticatedData," yaml:"authenticatedData"`
CheckingDisabled bool `json:"checkingDisabled," xml:"checkingDisabled," yaml:"checkingDisabled"`
}
// Question is a DNS Query.
type Question struct {
Name string `json:"name,omitempty" xml:"name,omitempty" yaml:",omitempty"`
Class string `json:"class,omitempty" xml:"class,omitempty" yaml:",omitempty"`
Type string `json:"type,omitempty" xml:"type,omitempty" yaml:",omitempty"`
Name string `json:"name,omitempty" xml:"name,omitempty" yaml:"name,omitempty"`
Class string `json:"class,omitempty" xml:"class,omitempty" yaml:"class,omitempty"`
Type string `json:"type,omitempty" xml:"type,omitempty" yaml:"type,omitempty"`
}
// RRHeader is for DNS Resource Headers.
type RRHeader struct {
Name string `json:"name,omitempty" xml:"name,omitempty" yaml:",omitempty"`
TTL string `json:"ttl,omitempty" xml:"ttl,omitempty" yaml:",omitempty"`
Class string `json:"class,omitempty" xml:"class,omitempty" yaml:",omitempty"`
Type string `json:"type,omitempty" xml:"type,omitempty" yaml:",omitempty"`
Name string `json:"name,omitempty" xml:"name,omitempty" yaml:"name,omitempty"`
TTL string `json:"ttl,omitempty" xml:"ttl,omitempty" yaml:"ttl,omitempty"`
Class string `json:"class,omitempty" xml:"class,omitempty" yaml:"class,omitempty"`
Type string `json:"type,omitempty" xml:"type,omitempty" yaml:"type,omitempty"`
Rdlength uint16 `json:"-" xml:"-" yaml:"-"`
}
// Opts is for the OPT pseudosection, nearly exclusively for EDNS.
type Opts struct {
Name string `json:"name,omitempty" xml:"name,omitempty" yaml:",omitempty"`
Value string `json:"value" xml:"value" yaml:""`
Value string `json:"value" xml:"value" yaml:"value"`
}
// Answer is for a DNS Response.
@ -54,199 +67,4 @@ type Answer struct {
RRHeader `json:"header,omitempty" xml:"header,omitempty" yaml:"header,omitempty"`
}
// ToString turns the response into something that looks a lot like dig
//
// Much of this is taken from https://github.com/miekg/dns/blob/master/msg.go#L900
func ToString(res util.Response, opts util.Options) (string, error) {
if res.DNS == nil {
return "<nil> MsgHdr", errNoMessage
}
var (
s string
opt *dns.OPT
)
if !opts.Short {
if opts.Display.Comments {
s += res.DNS.MsgHdr.String() + " "
s += "QUERY: " + strconv.Itoa(len(res.DNS.Question)) + ", "
s += "ANSWER: " + strconv.Itoa(len(res.DNS.Answer)) + ", "
s += "AUTHORITY: " + strconv.Itoa(len(res.DNS.Ns)) + ", "
s += "ADDITIONAL: " + strconv.Itoa(len(res.DNS.Extra)) + "\n"
opt = res.DNS.IsEdns0()
if opt != nil && opts.Display.Opt {
// OPT PSEUDOSECTION
s += opt.String() + "\n"
}
}
if opts.Display.Question {
if len(res.DNS.Question) > 0 {
if opts.Display.Comments {
s += "\n;; QUESTION SECTION:\n"
}
for _, r := range res.DNS.Question {
str, err := stringParse(r.String(), false, opts)
if err != nil {
return "", fmt.Errorf("%w", err)
}
s += str + "\n"
}
}
}
if opts.Display.Answer {
if len(res.DNS.Answer) > 0 {
if opts.Display.Comments {
s += "\n;; ANSWER SECTION:\n"
}
for _, r := range res.DNS.Answer {
if r != nil {
str, err := stringParse(r.String(), true, opts)
if err != nil {
return "", fmt.Errorf("%w", err)
}
s += str + "\n"
}
}
}
}
if opts.Display.Authority {
if len(res.DNS.Ns) > 0 {
if opts.Display.Comments {
s += "\n;; AUTHORITY SECTION:\n"
}
for _, r := range res.DNS.Ns {
if r != nil {
str, err := stringParse(r.String(), true, opts)
if err != nil {
return "", fmt.Errorf("%w", err)
}
s += str + "\n"
}
}
}
}
if opts.Display.Additional {
if len(res.DNS.Extra) > 0 && (opt == nil || len(res.DNS.Extra) > 1) {
if opts.Display.Comments {
s += "\n;; ADDITIONAL SECTION:\n"
}
for _, r := range res.DNS.Extra {
if r != nil && r.Header().Rrtype != dns.TypeOPT {
str, err := stringParse(r.String(), true, opts)
if err != nil {
return "", fmt.Errorf("%w", err)
}
s += str + "\n"
}
}
}
}
if opts.Display.Statistics {
s += "\n;; Query time: " + res.RTT.String()
// Add extra information to server string
var extra string
switch {
case opts.TCP:
extra = ":" + strconv.Itoa(opts.Port) + " (TCP)"
case opts.TLS:
extra = ":" + strconv.Itoa(opts.Port) + " (TLS)"
case opts.HTTPS, opts.DNSCrypt:
extra = ""
case opts.QUIC:
extra = ":" + strconv.Itoa(opts.Port) + " (QUIC)"
default:
extra = ":" + strconv.Itoa(opts.Port) + " (UDP)"
}
s += "\n;; SERVER: " + opts.Request.Server + extra
s += "\n;; WHEN: " + time.Now().Format(time.RFC1123Z)
s += "\n;; MSG SIZE rcvd: " + strconv.Itoa(res.DNS.Len()) + "\n"
}
} else {
// Print just the responses, nothing else
for i, resp := range res.DNS.Answer {
temp := strings.Split(resp.String(), "\t")
s += temp[len(temp)-1]
if opts.Identify {
s += " from server " + opts.Request.Server + " in " + res.RTT.String()
}
// Don't print newline on last line
if i != len(res.DNS.Answer)-1 {
s += "\n"
}
}
}
return s, nil
}
func stringParse(str string, isAns bool, opts util.Options) (string, error) {
split := strings.Split(str, "\t")
// Make edits if so requested
// TODO: make less ew?
// This exists because the question section should be left alone EXCEPT for punycode.
if isAns {
if !opts.ShowTTL {
// Remove from existence
split = append(split[:1], split[2:]...)
}
if !opts.ShowClass {
// Position depends on if the TTL is there or not.
if opts.ShowTTL {
split = append(split[:2], split[3:]...)
} else {
split = append(split[:1], split[2:]...)
}
}
if opts.ShowTTL && opts.HumanTTL {
ttl, _ := strconv.Atoi(split[1])
split[1] = (time.Duration(ttl) * time.Second).String()
}
}
if opts.Display.UcodeTranslate {
var (
err error
semi string
)
if strings.HasPrefix(split[0], ";") {
split[0] = strings.TrimPrefix(split[0], ";")
semi = ";"
}
split[0], err = idna.ToUnicode(split[0])
if err != nil {
return "", fmt.Errorf("punycode: %w", err)
}
split[0] = semi + split[0]
}
return strings.Join(split, "\t"), nil
}
var errNoMessage = errors.New("no message")

View file

@ -12,67 +12,133 @@ import (
// Options is the grand structure for all query options.
type Options struct {
Logger *logawl.Logger
TLSHost string
// The logger
Logger *logawl.Logger
// Host to verify TLS cert with
TLSHost string `json:"tlsHost"`
// EDNS Options
EDNS
Request Request
Port int
Verbosity int
Display Displays
TC bool
ShowTTL bool
ShowClass bool
ShowQuery bool
AA bool
AD bool
CD bool
QR bool
RD bool
RA bool
IPv4 bool
Z bool
Reverse bool
HumanTTL bool
Truncate bool
Short bool
Identify bool
JSON bool
XML bool
YAML bool
QUIC bool
HTTPS bool
TLSNoVerify bool
TLS bool
DNSCrypt bool
TCP bool
IPv6 bool
// DNS request :)
Request Request
// Verbosity levels, see [logawl.AllLevels]
Verbosity int `json:"-"`
// Display options
Display Display
// Ignore Truncation
Truncate bool `json:"ignoreTruncate"`
// Print only the answer
Short bool `json:"short"`
// When Short is true, display where the query came from
Identify bool `json:"identify"`
// Perform a reverse DNS query when true
Reverse bool `json:"reverse"`
HeaderFlags
// Display resposne as JSON
JSON bool `json:"-" xml:"-" yaml:"-"`
// Display response as XML
XML bool `json:"-" xml:"-" yaml:"-"`
// Display response as YAML
YAML bool `json:"-" xml:"-" yaml:"-"`
// Use TCP instead of UDP to make the query
TCP bool `json:"tcp"`
// Use DNS-over-TLS to make the query
TLS bool `json:"dns_over_tls"`
// When using TLS, ignore certificates
TLSNoVerify bool `json:"tlsNoVerify"`
// Use DNS-over-HTTPS to make the query
HTTPS bool `json:"dns_over_https"`
// Use DNS-over-QUIC to make the query
QUIC bool `json:"dns_over_quic"`
// Use DNSCrypt to make the query
DNSCrypt bool `json:"dnscrpyt"`
// Force IPv4 only
IPv4 bool `json:"force_IPv4"`
// Force IPv6 only
IPv6 bool `json:"force_IPv6"`
}
// Displays contains toggles for what to (and not to) display.
type Displays struct {
Comments bool
Question bool // QUESTION SECTION
Opt bool // OPT PSEUDOSECTION
Answer bool // ANSWER SECTION
Authority bool // AUTHORITY SECTION
Additional bool // ADDITIONAL SECTION
Statistics bool // Query time, message size, etc.
UcodeTranslate bool // Translate Punycode back to Unicode
// HeaderFlags are the flags that are in DNS headers.
type HeaderFlags struct {
// Authoritative Answer DNS query flag
AA bool `json:"authoritative,"`
// Authenticated Data DNS query flag
AD bool `json:"authenticatedData,"`
// Checking Disabled DNS query flag
CD bool `json:"checkingDisabled,"`
// QueRy DNS query flag
QR bool `json:"query"`
// Recursion Desired DNS query flag
RD bool `json:"recursionDesired"`
// Recursion Available DNS query flag
RA bool `json:"recursionAvailable"`
// TrunCated DNS query flag
TC bool `json:"truncated"`
// Zero DNS query flag
Z bool `json:"zero"`
}
// Display contains toggles for what to (and not to) display.
type Display struct {
/* Section displaying */
// Comments?
Comments bool `json:"comments"`
// QUESTION SECTION
Question bool `json:"question"`
// OPT PSEUDOSECTION
Opt bool `json:"opt"`
// ANSWER SECTION
Answer bool `json:"answer"`
// AUTHORITY SECTION
Authority bool `json:"authority"`
// ADDITIONAL SECTION
Additional bool `json:"additional"`
// Query time, message size, etc.
Statistics bool `json:"statistics"`
// Display TTL in response
TTL bool `json:"ttl"`
/* Answer formatting */
// Display Class in response
ShowClass bool `json:"showClass"`
// Display query before it is sent
ShowQuery bool `json:"showQuery"`
// Display TTL as human-readable
HumanTTL bool `json:"HumanTTL"`
// Translate Punycode back to Unicode
UcodeTranslate bool `json:"unicode"`
}
// EDNS contains toggles for various EDNS options.
type EDNS struct {
Subnet dns.EDNS0_SUBNET
ZFlag uint16
BufSize uint16
EnableEDNS bool
Cookie bool
DNSSEC bool
Expire bool
KeepOpen bool
Nsid bool
Padding bool
Version uint8
// Subnet to originate query from.
Subnet dns.EDNS0_SUBNET `json:"subnet"`
// Must Be Zero flag
ZFlag uint16 `json:"zflag"`
// UDP buffer size
BufSize uint16 `json:"bufSize"`
// Enable/Disable EDNS entirely
EnableEDNS bool `json:"edns"`
// Sending EDNS cookie
Cookie bool `json:"cookie"`
// Enabling DNSSEC
DNSSEC bool `json:"dnssec"`
// Sending EDNS Expire
Expire bool `json:"expire"`
// Sending EDNS TCP keepopen
KeepOpen bool `json:"keepOpen"`
// Sending EDNS NSID
Nsid bool `json:"nsid"`
// Send EDNS Padding
Padding bool `json:"padding"`
// Set EDNS version (default: 0)
Version uint8 `json:"version"`
}
// ParseSubnet takes a subnet argument and makes it into one that the DNS library

View file

@ -10,16 +10,26 @@ import (
// Response is the DNS response.
type Response struct {
DNS *dns.Msg // The full DNS response
RTT time.Duration `json:"rtt"` // The time it took to make the DNS query
// The full DNS response
DNS *dns.Msg `json:"response"`
// The time it took to make the DNS query
RTT time.Duration `json:"rtt"`
}
// Request is a structure for a DNS query.
type Request struct {
Server string `json:"server"`
Name string `json:"name"`
Timeout time.Duration
Retries int
Type uint16 `json:"request"`
Class uint16 `json:"class"`
// Server to query, eg. 8.8.8.8
Server string `json:"server"`
// Domain to query, eg. example.com
Name string `json:"name"`
// Duration to wait until marking request as failed
Timeout time.Duration `json:"timeout"`
// Port to make DNS request on
Port int `json:"port"`
// Number of failures to make before giving up
Retries int `json:"retries"`
// Request type, eg. A, AAAA, NAPTR
Type uint16 `json:"type"`
// Request class, eg. IN
Class uint16 `json:"class"`
}