feat: Allow opt pseudosection to be printed #91
10 changed files with 175 additions and 16 deletions
|
@ -13,6 +13,7 @@ import (
|
|||
)
|
||||
|
||||
// GetDNSConfig gets DNS information from Plan 9, because it's different from UNIX and Windows.
|
||||
//
|
||||
// Plan 9 stores its network data in /net/ndb, which seems to be formatted a specific way
|
||||
// Yoink it and use it.
|
||||
//
|
||||
|
|
18
conf/wasm.go
Normal file
18
conf/wasm.go
Normal file
|
@ -0,0 +1,18 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
//go:build js
|
||||
|
||||
package conf
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// GetDNSConfig doesn't do anything, because it is impossible (and bad security)
|
||||
// if it could, as that is the definition of a DNS leak.
|
||||
func GetDNSConfig() (*dns.ClientConfig, error) {
|
||||
return nil, errNotImplemented
|
||||
}
|
||||
|
||||
var errNotImplemented = errors.New("not implemented")
|
2
go.mod
2
go.mod
|
@ -22,7 +22,7 @@ require (
|
|||
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-20220827204233-334a2380cb91 // indirect
|
||||
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
2
go.sum
2
go.sum
|
@ -81,6 +81,8 @@ golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5
|
|||
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/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=
|
||||
|
|
1
main.go
1
main.go
|
@ -1,4 +1,5 @@
|
|||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
//go:build !js
|
||||
|
||||
package main
|
||||
|
||||
|
|
|
@ -36,10 +36,7 @@ func TestResolve(t *testing.T) {
|
|||
assert.ErrorContains(t, err, "timeout")
|
||||
}
|
||||
|
||||
// FIXME: See when this is fixed and fix it.
|
||||
|
||||
func TestTruncate(t *testing.T) {
|
||||
t.Skip("Sadly this is broken.")
|
||||
t.Parallel()
|
||||
|
||||
opts := util.Options{
|
||||
|
|
129
query/print.go
129
query/print.go
|
@ -3,6 +3,7 @@
|
|||
package query
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
|
@ -178,7 +179,7 @@ func MakePrintable(msg *dns.Msg, opts util.Options) (*Message, error) {
|
|||
name = additional.Header().Name
|
||||
}
|
||||
|
||||
ret.Extra = append(ret.Extra, Answer{
|
||||
ret.Additional = append(ret.Additional, Answer{
|
||||
RRHeader: RRHeader{
|
||||
Name: name,
|
||||
Type: dns.TypeToString[additional.Header().Rrtype],
|
||||
|
@ -191,7 +192,133 @@ func MakePrintable(msg *dns.Msg, opts util.Options) (*Message, error) {
|
|||
}
|
||||
}
|
||||
|
||||
opt := msg.IsEdns0()
|
||||
if opt != nil && opts.Display.Opt {
|
||||
ret.Opt, err = parseOpt(*opt)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("edns print: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return &ret, nil
|
||||
}
|
||||
|
||||
func parseOpt(rr dns.OPT) ([]Opts, error) {
|
||||
ret := []Opts{}
|
||||
// Most of this is taken from https://github.com/miekg/dns/blob/master/edns.go#L76
|
||||
|
||||
ret = append(ret, Opts{
|
||||
Name: "Version",
|
||||
Value: strconv.Itoa(int(rr.Version())),
|
||||
})
|
||||
|
||||
if rr.Do() {
|
||||
ret = append(ret, Opts{
|
||||
Name: "Flags",
|
||||
Value: "do",
|
||||
})
|
||||
} else {
|
||||
ret = append(ret, Opts{
|
||||
Name: "Flags",
|
||||
Value: "",
|
||||
})
|
||||
}
|
||||
|
||||
if rr.Hdr.Ttl&0x7FFF != 0 {
|
||||
ret = append(ret, Opts{
|
||||
Name: "MBZ",
|
||||
Value: fmt.Sprintf("0x%04x", rr.Hdr.Ttl&0x7FFF),
|
||||
})
|
||||
}
|
||||
|
||||
ret = append(ret, Opts{
|
||||
Name: "UDP Buffer Size",
|
||||
Value: strconv.Itoa(int(rr.UDPSize())),
|
||||
})
|
||||
|
||||
for _, opt := range rr.Option {
|
||||
switch opt.(type) {
|
||||
case *dns.EDNS0_NSID:
|
||||
str := opt.String()
|
||||
|
||||
hex, err := hex.DecodeString(str)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w", err)
|
||||
}
|
||||
|
||||
ret = append(ret, Opts{
|
||||
Name: "NSID",
|
||||
Value: fmt.Sprintf("%s (%s)", str, string(hex)),
|
||||
})
|
||||
case *dns.EDNS0_SUBNET:
|
||||
ret = append(ret, Opts{
|
||||
Name: "Subnet",
|
||||
Value: opt.String(),
|
||||
})
|
||||
case *dns.EDNS0_COOKIE:
|
||||
ret = append(ret, Opts{
|
||||
Name: "Cookie",
|
||||
Value: opt.String(),
|
||||
})
|
||||
case *dns.EDNS0_EXPIRE:
|
||||
ret = append(ret, Opts{
|
||||
Name: "Expire",
|
||||
Value: opt.String(),
|
||||
})
|
||||
case *dns.EDNS0_TCP_KEEPALIVE:
|
||||
ret = append(ret, Opts{
|
||||
Name: "TCP Keepalive",
|
||||
Value: opt.String(),
|
||||
})
|
||||
case *dns.EDNS0_UL:
|
||||
ret = append(ret, Opts{
|
||||
Name: "Update Lease",
|
||||
Value: opt.String(),
|
||||
})
|
||||
case *dns.EDNS0_LLQ:
|
||||
ret = append(ret, Opts{
|
||||
Name: "Long Lived Queries",
|
||||
Value: opt.String(),
|
||||
})
|
||||
case *dns.EDNS0_DAU:
|
||||
ret = append(ret, Opts{
|
||||
Name: "DNSSEC Algorithm Understood",
|
||||
Value: opt.String(),
|
||||
})
|
||||
case *dns.EDNS0_DHU:
|
||||
ret = append(ret, Opts{
|
||||
Name: "DS Hash Understood",
|
||||
Value: opt.String(),
|
||||
})
|
||||
case *dns.EDNS0_N3U:
|
||||
ret = append(ret, Opts{
|
||||
Name: "NSEC3 Hash Understood",
|
||||
Value: opt.String(),
|
||||
})
|
||||
case *dns.EDNS0_LOCAL:
|
||||
ret = append(ret, Opts{
|
||||
Name: "Local OPT",
|
||||
Value: opt.String(),
|
||||
})
|
||||
case *dns.EDNS0_PADDING:
|
||||
ret = append(ret, Opts{
|
||||
Name: "Padding",
|
||||
Value: opt.String(),
|
||||
})
|
||||
case *dns.EDNS0_EDE:
|
||||
ret = append(ret, Opts{
|
||||
Name: "EDE",
|
||||
Value: opt.String(),
|
||||
})
|
||||
case *dns.EDNS0_ESU:
|
||||
ret = append(ret, Opts{
|
||||
Name: "ESU",
|
||||
Value: opt.String(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
var errInvalidFormat = errors.New("this should never happen")
|
||||
|
|
|
@ -37,12 +37,16 @@ func TestCreateQ(t *testing.T) {
|
|||
Statistics: true,
|
||||
},
|
||||
EDNS: util.EDNS{
|
||||
ZFlag: 1,
|
||||
BufSize: 1500,
|
||||
EnableEDNS: true,
|
||||
DNSSEC: true,
|
||||
Cookie: true,
|
||||
DNSSEC: true,
|
||||
Expire: true,
|
||||
KeepOpen: true,
|
||||
Nsid: true,
|
||||
Padding: true,
|
||||
Version: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
@ -15,30 +15,39 @@ import (
|
|||
)
|
||||
|
||||
// Message is for overall DNS responses.
|
||||
//
|
||||
//nolint:govet // Better output is worth 32 bytes.
|
||||
type Message struct {
|
||||
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"`
|
||||
Extra []Answer `json:"extra,omitempty" xml:"extra,omitempty" yaml:",omitempty"`
|
||||
Header dns.MsgHdr `json:"header,omitempty" xml:"header,omitempty" yaml:",omitempty"`
|
||||
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"`
|
||||
}
|
||||
|
||||
// Question is a DNS Query.
|
||||
type Question struct {
|
||||
Name string `json:"name,omitempty" xml:"name,omitempty" yaml:",omitempty"`
|
||||
Type string `json:"type,omitempty" xml:"type,omitempty" yaml:",omitempty"`
|
||||
Class string `json:"class,omitempty" xml:"class,omitempty" yaml:",omitempty"`
|
||||
Type string `json:"type,omitempty" xml:"type,omitempty" yaml:",omitempty"`
|
||||
}
|
||||
|
||||
// RRHeader is for DNS Resource Headers.
|
||||
type RRHeader struct {
|
||||
Name string `json:"name,omitempty" xml:"name,omitempty" yaml:",omitempty"`
|
||||
Type string `json:"type,omitempty" xml:"type,omitempty" yaml:",omitempty"`
|
||||
Class string `json:"class,omitempty" xml:"class,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"`
|
||||
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:""`
|
||||
}
|
||||
|
||||
// Answer is for a DNS Response.
|
||||
type Answer struct {
|
||||
Value string `json:"response,omitempty" xml:"response,omitempty" yaml:"response,omitempty"`
|
||||
|
@ -212,7 +221,7 @@ func stringParse(str string, isAns bool, opts util.Options) (string, error) {
|
|||
}
|
||||
}
|
||||
|
||||
if opts.HumanTTL {
|
||||
if opts.ShowTTL && opts.HumanTTL {
|
||||
ttl, _ := strconv.Atoi(split[1])
|
||||
split[1] = (time.Duration(ttl) * time.Second).String()
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// Options is the grand CLI options structure.
|
||||
// Options is the grand structure for all query options.
|
||||
type Options struct {
|
||||
Logger *logawl.Logger
|
||||
TLSHost string
|
||||
|
|
Loading…
Reference in a new issue