First pass for edns subnet support
This commit is contained in:
parent
29365cc9d8
commit
1bf0864632
78
edns.go
78
edns.go
|
@ -2,18 +2,19 @@ package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EDNS0 Option codes.
|
// EDNS0 Option codes.
|
||||||
const (
|
const (
|
||||||
_ = iota
|
_ = iota
|
||||||
EDNS0LLQ // not used
|
EDNS0LLQ // not used
|
||||||
EDNS0UL // not used
|
EDNS0UL // not used
|
||||||
EDNS0NSID // NSID, RFC5001
|
EDNS0NSID // NSID, RFC5001
|
||||||
EDNS0SUBNET = 0x50fa // client-subnet draft
|
EDNS0SUBNET = 0x50fa // client-subnet draft
|
||||||
_DO = 1 << 7 // dnssec ok
|
_DO = 1 << 7 // dnssec ok
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -58,6 +59,8 @@ func (rr *RR_OPT) String() string {
|
||||||
}
|
}
|
||||||
s += " " + r
|
s += " " + r
|
||||||
}
|
}
|
||||||
|
case *EDNS0_SUBNET:
|
||||||
|
s += "\n; SUBNET: " + o.String()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
|
@ -130,8 +133,8 @@ type EDNS0 interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type EDNS0_NSID struct {
|
type EDNS0_NSID struct {
|
||||||
Code uint16
|
Code uint16 // Always EDNS0NSID
|
||||||
Nsid string // This string needs to be hex encoded
|
Nsid string // This string needs to be hex encoded
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *EDNS0_NSID) Option() uint16 {
|
func (e *EDNS0_NSID) Option() uint16 {
|
||||||
|
@ -155,9 +158,70 @@ func (e *EDNS0_NSID) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
type EDNS0_SUBNET struct {
|
type EDNS0_SUBNET struct {
|
||||||
Code uint16
|
Code uint16 // Always EDNS0SUBNET
|
||||||
Family uint16
|
Family uint16 // 1 for IP, 2 for IP6
|
||||||
SourceNetmask uint8
|
SourceNetmask uint8
|
||||||
SourceScope uint8
|
SourceScope uint8
|
||||||
Address []net.IP
|
Address net.IP
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EDNS0_SUBNET) Option() uint16 {
|
||||||
|
return e.Code
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EDNS0_SUBNET) Pack() ([]byte, error) {
|
||||||
|
b := make([]byte, 4)
|
||||||
|
b[0], b[1] = packUint16(e.Family)
|
||||||
|
b[2] = e.SourceNetmask
|
||||||
|
b[3] = e.SourceScope
|
||||||
|
switch e.Family {
|
||||||
|
case 1:
|
||||||
|
// just copy? TODO (also in msg.go...)
|
||||||
|
ip := make([]byte, net.IPv4len)
|
||||||
|
for i := 0; i < net.IPv4len; i++ {
|
||||||
|
if i+1 > len(e.Address) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
ip[i] = e.Address[i]
|
||||||
|
}
|
||||||
|
b = append(b, ip...)
|
||||||
|
case 2:
|
||||||
|
ip := make([]byte, net.IPv6len)
|
||||||
|
for i := 0; i < net.IPv6len; i++ {
|
||||||
|
if i+1 > len(e.Address) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
ip[i] = e.Address[i]
|
||||||
|
}
|
||||||
|
b = append(b, ip...)
|
||||||
|
default:
|
||||||
|
return nil, errors.New("bad address family")
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EDNS0_SUBNET) Unpack(b []byte) {
|
||||||
|
// TODO: length of b
|
||||||
|
e.Family, _ = unpackUint16(b, 0)
|
||||||
|
e.SourceNetmask = b[2]
|
||||||
|
e.SourceScope = b[3]
|
||||||
|
switch e.Family {
|
||||||
|
case 1:
|
||||||
|
if len(b) == 8 {
|
||||||
|
e.Address = net.IPv4(b[4], b[5], b[6], b[7])
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if len(b) == 20 {
|
||||||
|
e.Address = net.IP{b[4], b[4+1], b[4+2], b[4+3], b[4+4],
|
||||||
|
b[4+5], b[4+6], b[4+7], b[4+8], b[4+9], b[4+10],
|
||||||
|
b[4+11], b[4+12], b[4+13], b[4+14], b[4+15]}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EDNS0_SUBNET) String() string {
|
||||||
|
return e.Address.String() + "/" +
|
||||||
|
strconv.Itoa(int(e.SourceNetmask)) + "/" +
|
||||||
|
strconv.Itoa(int(e.SourceScope))
|
||||||
}
|
}
|
||||||
|
|
28
ex/q/q.go
28
ex/q/q.go
|
@ -4,6 +4,7 @@ import (
|
||||||
"dns"
|
"dns"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -47,7 +48,8 @@ func main() {
|
||||||
rd := flag.Bool("rd", true, "set RD flag in query")
|
rd := flag.Bool("rd", true, "set RD flag in query")
|
||||||
fallback := flag.Bool("fallback", false, "fallback to 4096 bytes bufsize and after that TCP")
|
fallback := flag.Bool("fallback", false, "fallback to 4096 bytes bufsize and after that TCP")
|
||||||
tcp := flag.Bool("tcp", false, "TCP mode")
|
tcp := flag.Bool("tcp", false, "TCP mode")
|
||||||
nsid := flag.Bool("nsid", false, "ask for NSID")
|
nsid := flag.Bool("nsid", false, "set edns nsid option")
|
||||||
|
client := flag.String("client", "", "set edns client-subnet option")
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
fmt.Fprintf(os.Stderr, "Usage: %s [@server] [qtype] [qclass] [name ...]\n", os.Args[0])
|
fmt.Fprintf(os.Stderr, "Usage: %s [@server] [qtype] [qclass] [name ...]\n", os.Args[0])
|
||||||
flag.PrintDefaults()
|
flag.PrintDefaults()
|
||||||
|
@ -162,7 +164,8 @@ Flags:
|
||||||
m.MsgHdr.CheckingDisabled = *cd
|
m.MsgHdr.CheckingDisabled = *cd
|
||||||
m.MsgHdr.RecursionDesired = *rd
|
m.MsgHdr.RecursionDesired = *rd
|
||||||
m.Question = make([]dns.Question, 1)
|
m.Question = make([]dns.Question, 1)
|
||||||
if *dnssec || *nsid {
|
|
||||||
|
if *dnssec || *nsid || *client != "" {
|
||||||
o := new(dns.RR_OPT)
|
o := new(dns.RR_OPT)
|
||||||
o.Hdr.Name = "."
|
o.Hdr.Name = "."
|
||||||
o.Hdr.Rrtype = dns.TypeOPT
|
o.Hdr.Rrtype = dns.TypeOPT
|
||||||
|
@ -171,12 +174,26 @@ Flags:
|
||||||
o.SetUDPSize(dns.DefaultMsgSize)
|
o.SetUDPSize(dns.DefaultMsgSize)
|
||||||
}
|
}
|
||||||
if *nsid {
|
if *nsid {
|
||||||
// Ask for it
|
|
||||||
e := new(dns.EDNS0_NSID)
|
e := new(dns.EDNS0_NSID)
|
||||||
e.Nsid = ""
|
|
||||||
e.Code = dns.EDNS0NSID
|
e.Code = dns.EDNS0NSID
|
||||||
o.Option = append(o.Option, e)
|
o.Option = append(o.Option, e)
|
||||||
}
|
}
|
||||||
|
if *client != "" {
|
||||||
|
e := new(dns.EDNS0_SUBNET)
|
||||||
|
e.Code = dns.EDNS0SUBNET
|
||||||
|
e.SourceNetmask = 0
|
||||||
|
e.SourceScope = 0
|
||||||
|
e.Address = net.ParseIP(*client)
|
||||||
|
if e.Address == nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Failure to parse IP address: %s\n", *client)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.Family = 1 // IP4
|
||||||
|
if len(e.Address) > net.IPv4len {
|
||||||
|
e.Family = 2 // IP6
|
||||||
|
}
|
||||||
|
o.Option = append(o.Option, e)
|
||||||
|
}
|
||||||
m.Extra = append(m.Extra, o)
|
m.Extra = append(m.Extra, o)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,8 +260,7 @@ forever:
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("%v", r.Reply)
|
fmt.Printf("%v", r.Reply)
|
||||||
fmt.Printf("\n;; query time: %.3d µs, server: %s(%s), size: %dB\n", r.Rtt/1e3, r.RemoteAddr, r.RemoteAddr.Network(), r.Reply.Len())
|
fmt.Printf("\n;; query time: %.3d µs, server: %s(%s), size: %d bytes\n", r.Rtt/1e3, r.RemoteAddr, r.RemoteAddr.Network(), r.Reply.Len())
|
||||||
// Server maybe
|
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
if i == len(qname) {
|
if i == len(qname) {
|
||||||
|
|
7
msg.go
7
msg.go
|
@ -404,7 +404,7 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
|
||||||
element := val.Field(i).Index(j).Interface()
|
element := val.Field(i).Index(j).Interface()
|
||||||
b, e := element.(EDNS0).Pack()
|
b, e := element.(EDNS0).Pack()
|
||||||
if e != nil {
|
if e != nil {
|
||||||
println("dns: failure packing OTP")
|
println("dns: failure packing OPT")
|
||||||
return lenmsg, false
|
return lenmsg, false
|
||||||
}
|
}
|
||||||
// Option code
|
// Option code
|
||||||
|
@ -707,7 +707,10 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok boo
|
||||||
edns = append(edns, e)
|
edns = append(edns, e)
|
||||||
off = off1 + int(optlen)
|
off = off1 + int(optlen)
|
||||||
case EDNS0SUBNET:
|
case EDNS0SUBNET:
|
||||||
// ..
|
e := new(EDNS0_SUBNET)
|
||||||
|
e.Unpack(msg[off1 : off1+int(optlen)])
|
||||||
|
edns = append(edns, e)
|
||||||
|
off = off1 + int(optlen)
|
||||||
}
|
}
|
||||||
fv.Set(reflect.ValueOf(edns))
|
fv.Set(reflect.ValueOf(edns))
|
||||||
// goto ??
|
// goto ??
|
||||||
|
|
Loading…
Reference in New Issue