Changes applied:

* Renamed EDNS0_CUSTOM to EDNS0_LOCAL
* Added EDNS0LOCAL constants
* Added documentation
This commit is contained in:
Harvo Jones 2015-03-18 12:12:53 -07:00
parent 8bd3ac773f
commit 57d8407ad7
3 changed files with 47 additions and 28 deletions

View File

@ -1,6 +1,7 @@
package dns package dns
import ( import (
"strconv"
"testing" "testing"
"time" "time"
) )
@ -62,19 +63,23 @@ func TestClientEDNS0(t *testing.T) {
} }
} }
// Validates the transmission and parsing of custom EDNS0 options. // Validates the transmission and parsing of local EDNS0 options.
func TestClientEDNS0Custom(t *testing.T) { func TestClientEDNS0Local(t *testing.T) {
optStr1 := "1979:0x0707"
optStr2 := strconv.Itoa(EDNS0LOCALSTART) + ":0x0601"
handler := func(w ResponseWriter, req *Msg) { handler := func(w ResponseWriter, req *Msg) {
m := new(Msg) m := new(Msg)
m.SetReply(req) m.SetReply(req)
m.Extra = make([]RR, 1, 2) m.Extra = make([]RR, 1, 2)
m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello custom edns"}} m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello local edns"}}
// If the custom options are what we expect, then reflect them back. // If the local options are what we expect, then reflect them back.
ec1 := req.Extra[0].(*OPT).Option[0].(*EDNS0_CUSTOM).String() ec1 := req.Extra[0].(*OPT).Option[0].(*EDNS0_LOCAL).String()
ec2 := req.Extra[0].(*OPT).Option[1].(*EDNS0_CUSTOM).String() ec2 := req.Extra[0].(*OPT).Option[1].(*EDNS0_LOCAL).String()
if ec1 == "1979:0x0707" && ec2 == "1997:0x0601" { if ec1 == optStr1 && ec2 == optStr2 {
m.Extra = append(m.Extra, req.Extra[0]) m.Extra = append(m.Extra, req.Extra[0])
} }
@ -93,8 +98,9 @@ func TestClientEDNS0Custom(t *testing.T) {
m := new(Msg) m := new(Msg)
m.SetQuestion("miek.nl.", TypeTXT) m.SetQuestion("miek.nl.", TypeTXT)
ec1 := &EDNS0_CUSTOM{Code: 1979, Data: []byte{7, 7}} // Add two local edns options to the query.
ec2 := &EDNS0_CUSTOM{Code: 1997, Data: []byte{6, 1}} ec1 := &EDNS0_LOCAL{Code: 1979, Data: []byte{7, 7}}
ec2 := &EDNS0_LOCAL{Code: EDNS0LOCALSTART, Data: []byte{6, 1}}
o := &OPT{Hdr: RR_Header{Name: ".", Rrtype: TypeOPT}, Option: []EDNS0{ec1, ec2}} o := &OPT{Hdr: RR_Header{Name: ".", Rrtype: TypeOPT}, Option: []EDNS0{ec1, ec2}}
m.Extra = append(m.Extra, o) m.Extra = append(m.Extra, o)
@ -112,24 +118,22 @@ func TestClientEDNS0Custom(t *testing.T) {
} }
txt := r.Extra[0].(*TXT).Txt[0] txt := r.Extra[0].(*TXT).Txt[0]
if txt != "Hello custom edns" { if txt != "Hello local edns" {
t.Log("Unexpected result for miek.nl", txt, "!= Hello custom edns") t.Log("Unexpected result for miek.nl", txt, "!= Hello local edns")
t.Fail() t.Fail()
} }
// Validate the custom options in the reply. // Validate the local options in the reply.
exp := "1979:0x0707" got := r.Extra[1].(*OPT).Option[0].(*EDNS0_LOCAL).String()
got := r.Extra[1].(*OPT).Option[0].(*EDNS0_CUSTOM).String() if got != optStr1 {
if got != exp { t.Log("failed to get local edns0 answer; got %s, expected %s", got, optStr1)
t.Log("failed to get custom edns0 answer; got %s, expected %s", got, exp)
t.Fail() t.Fail()
t.Logf("%v\n", r) t.Logf("%v\n", r)
} }
exp = "1997:0x0601" got = r.Extra[1].(*OPT).Option[1].(*EDNS0_LOCAL).String()
got = r.Extra[1].(*OPT).Option[1].(*EDNS0_CUSTOM).String() if got != optStr2 {
if got != exp { t.Log("failed to get local edns0 answer; got %s, expected %s", got, optStr2)
t.Log("failed to get custom edns0 answer; got %s, expected %s", got, exp)
t.Fail() t.Fail()
t.Logf("%v\n", r) t.Logf("%v\n", r)
} }

29
edns.go
View File

@ -18,6 +18,8 @@ const (
EDNS0SUBNET = 0x8 // client-subnet (RFC6891) EDNS0SUBNET = 0x8 // client-subnet (RFC6891)
EDNS0EXPIRE = 0x9 // EDNS0 expire EDNS0EXPIRE = 0x9 // EDNS0 expire
EDNS0SUBNETDRAFT = 0x50fa // Don't use! Use EDNS0SUBNET EDNS0SUBNETDRAFT = 0x50fa // Don't use! Use EDNS0SUBNET
EDNS0LOCALSTART = 0xFDE9 // Beginning of range reserved for local/experimental use (RFC6891)
EDNS0LOCALEND = 0xFFFE // End of range reserved for local/experimental use (RFC6891)
_DO = 1 << 15 // dnssec ok _DO = 1 << 15 // dnssec ok
) )
@ -68,8 +70,8 @@ func (rr *OPT) String() string {
s += "\n; DS HASH UNDERSTOOD: " + o.String() s += "\n; DS HASH UNDERSTOOD: " + o.String()
case *EDNS0_N3U: case *EDNS0_N3U:
s += "\n; NSEC3 HASH UNDERSTOOD: " + o.String() s += "\n; NSEC3 HASH UNDERSTOOD: " + o.String()
case *EDNS0_CUSTOM: case *EDNS0_LOCAL:
s += "\n; CUSTOM OPT: " + o.String() s += "\n; LOCAL OPT: " + o.String()
} }
} }
return s return s
@ -479,17 +481,30 @@ func (e *EDNS0_EXPIRE) unpack(b []byte) error {
return nil return nil
} }
type EDNS0_CUSTOM struct { // The local EDNS0 option is used for local/experimental purposes. The option
// code is recommended to be within the range [EDNS0LOCALSTART, EDNS0LOCALEND]
// (RFC6891), although any unassigned code can actually be used. The content of
// the option is made available in Data, unaltered.
// Basic use pattern for creating a local option:
//
// o := new(dns.OPT)
// o.Hdr.Name = "."
// o.Hdr.Rrtype = dns.TypeOPT
// e := new(dns.EDNS0_LOCAL)
// e.Code = dns.EDNS0LOCALSTART
// e.Data = []byte{72, 82, 74}
// o.Option = append(o.Option, e)
type EDNS0_LOCAL struct {
Code uint16 Code uint16
Data []byte Data []byte
} }
func (e *EDNS0_CUSTOM) Option() uint16 { return e.Code } func (e *EDNS0_LOCAL) Option() uint16 { return e.Code }
func (e *EDNS0_CUSTOM) String() string { func (e *EDNS0_LOCAL) String() string {
return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data) return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data)
} }
func (e *EDNS0_CUSTOM) pack() ([]byte, error) { func (e *EDNS0_LOCAL) pack() ([]byte, error) {
b := make([]byte, len(e.Data)) b := make([]byte, len(e.Data))
copied := copy(b, e.Data) copied := copy(b, e.Data)
if copied != len(e.Data) { if copied != len(e.Data) {
@ -498,7 +513,7 @@ func (e *EDNS0_CUSTOM) pack() ([]byte, error) {
return b, nil return b, nil
} }
func (e *EDNS0_CUSTOM) unpack(b []byte) error { func (e *EDNS0_LOCAL) unpack(b []byte) error {
e.Data = make([]byte, len(b)) e.Data = make([]byte, len(b))
copied := copy(e.Data, b) copied := copy(e.Data, b)
if copied != len(b) { if copied != len(b) {

2
msg.go
View File

@ -1048,7 +1048,7 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
edns = append(edns, e) edns = append(edns, e)
off = off1 + int(optlen) off = off1 + int(optlen)
default: default:
e := new(EDNS0_CUSTOM) e := new(EDNS0_LOCAL)
e.Code = code e.Code = code
if err := e.unpack(msg[off1 : off1+int(optlen)]); err != nil { if err := e.unpack(msg[off1 : off1+int(optlen)]); err != nil {
return lenmsg, err return lenmsg, err