Merge branch 'ipseckey'

Tentatively merging.
This commit is contained in:
Miek Gieben 2015-01-27 08:17:50 +00:00
commit 50890090cb
6 changed files with 208 additions and 49 deletions

View File

@ -96,7 +96,8 @@ Example programs can be found in the `github.com/miekg/exdns` repository.
* 3225 - DO bit (DNSSEC OK)
* 340{1,2,3} - NAPTR record
* 3445 - Limiting the scope of (DNS)KEY
* 3597 - Unkown RRs
* 3597 - Unknown RRs
* 4025 - IPSECKEY
* 403{3,4,5} - DNSSEC + validation functions
* 4255 - SSHFP record
* 4343 - Case insensitivity

View File

@ -509,3 +509,30 @@ func TestCopy(t *testing.T) {
t.Fatalf("Copy() failed %s != %s", rr.String(), rr1.String())
}
}
func TestPackIPSECKEY(t *testing.T) {
tests := []string{
"38.2.0.192.in-addr.arpa. 7200 IN IPSECKEY ( 10 1 2 192.0.2.38 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )",
"38.2.0.192.in-addr.arpa. 7200 IN IPSECKEY ( 10 0 2 . AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )",
"38.2.0.192.in-addr.arpa. 7200 IN IPSECKEY ( 10 1 2 192.0.2.3 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )",
"38.1.0.192.in-addr.arpa. 7200 IN IPSECKEY ( 10 3 2 mygateway.example.com. AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )",
"0.d.4.0.3.0.e.f.f.f.3.f.0.1.2.0 7200 IN IPSECKEY ( 10 2 2 2001:0DB8:0:8002::2000:1 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )",
}
buf := make([]byte, 1024)
for _, t1 := range tests {
rr, _ := NewRR(t1)
off, e := PackRR(rr, buf, 0, nil, false)
if e != nil {
t.Logf("failed to pack IPSECKEY %s: %s\n", e, t1)
t.Fail()
continue
}
rr, _, e = UnpackRR(buf[:off], 0)
if e != nil {
t.Logf("failed to unpack IPSECKEY %s: %s\n", e, t1)
t.Fail()
}
t.Logf("%s\n", rr)
}
}

38
msg.go
View File

@ -652,6 +652,12 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
off += len(b)
}
case `dns:"a"`:
if val.Type().String() == "dns.IPSECKEY" {
// Field(2) is GatewayType, must be 1
if val.Field(2).Uint() != 1 {
continue
}
}
// It must be a slice of 4, even if it is 16, we encode
// only the first 4
if off+net.IPv4len > lenmsg {
@ -676,6 +682,12 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
return lenmsg, &Error{err: "overflow packing a"}
}
case `dns:"aaaa"`:
if val.Type().String() == "dns.IPSECKEY" {
// Field(2) is GatewayType, must be 2
if val.Field(2).Uint() != 2 {
continue
}
}
if fv.Len() == 0 {
break
}
@ -821,6 +833,13 @@ func packStructValue(val reflect.Value, msg []byte, off int, compression map[str
copy(msg[off:off+len(b64)], b64)
off += len(b64)
case `dns:"domain-name"`:
if val.Type().String() == "dns.IPSECKEY" {
// Field(2) is GatewayType, 1 and 2 or used for addresses
x := val.Field(2).Uint()
if x == 1 || x == 2 {
continue
}
}
if off, err = PackDomainName(s, msg, off, compression, false && compress); err != nil {
return lenmsg, err
}
@ -1025,6 +1044,12 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
}
fv.Set(reflect.ValueOf(edns))
case `dns:"a"`:
if val.Type().String() == "dns.IPSECKEY" {
// Field(2) is GatewayType, must be 1
if val.Field(2).Uint() != 1 {
continue
}
}
if off == lenrd {
break // dyn. update
}
@ -1034,6 +1059,12 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
fv.Set(reflect.ValueOf(net.IPv4(msg[off], msg[off+1], msg[off+2], msg[off+3])))
off += net.IPv4len
case `dns:"aaaa"`:
if val.Type().String() == "dns.IPSECKEY" {
// Field(2) is GatewayType, must be 2
if val.Field(2).Uint() != 2 {
continue
}
}
if off == lenrd {
break
}
@ -1230,6 +1261,13 @@ func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, err er
case `dns:"cdomain-name"`:
fallthrough
case `dns:"domain-name"`:
if val.Type().String() == "dns.IPSECKEY" {
// Field(2) is GatewayType, 1 and 2 or used for addresses
x := val.Field(2).Uint()
if x == 1 || x == 2 {
continue
}
}
if off == lenmsg {
// zero rdata foo, OK for dyn. updates
break

View File

@ -1373,3 +1373,37 @@ func TestPrintfVerbsRdata(t *testing.T) {
t.Errorf("should be empty")
}
}
func TestParseIPSECKEY(t *testing.T) {
tests := []string{
"38.2.0.192.in-addr.arpa. 7200 IN IPSECKEY ( 10 1 2 192.0.2.38 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )",
"38.2.0.192.in-addr.arpa.\t7200\tIN\tIPSECKEY\t10 1 2 192.0.2.38 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==",
"38.2.0.192.in-addr.arpa. 7200 IN IPSECKEY ( 10 0 2 . AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )",
"38.2.0.192.in-addr.arpa.\t7200\tIN\tIPSECKEY\t10 0 2 . AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==",
"38.2.0.192.in-addr.arpa. 7200 IN IPSECKEY ( 10 1 2 192.0.2.3 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )",
"38.2.0.192.in-addr.arpa.\t7200\tIN\tIPSECKEY\t10 1 2 192.0.2.3 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==",
"38.1.0.192.in-addr.arpa. 7200 IN IPSECKEY ( 10 3 2 mygateway.example.com. AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )",
"38.1.0.192.in-addr.arpa.\t7200\tIN\tIPSECKEY\t10 3 2 mygateway.example.com. AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==",
"0.d.4.0.3.0.e.f.f.f.3.f.0.1.2.0 7200 IN IPSECKEY ( 10 2 2 2001:0DB8:0:8002::2000:1 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ== )",
"0.d.4.0.3.0.e.f.f.f.3.f.0.1.2.0.\t7200\tIN\tIPSECKEY\t10 2 2 2001:db8:0:8002::2000:1 AQNRU3mG7TVTO2BkR47usntb102uFJtugbo6BSGvgqt4AQ==",
}
for i := 0; i < len(tests)-1; i++ {
t1 := tests[i]
e1 := tests[i+1]
r, e := NewRR(t1)
if e != nil {
t.Logf("failed to parse IPSECKEY %s", e)
continue
}
if r.String() != e1 {
t.Logf("these two IPSECKEY records should match")
t.Logf("\n%s\n%s\n", r.String(), e1)
t.Fail()
}
i++
}
}

View File

@ -1031,28 +1031,57 @@ func (rr *SSHFP) String() string {
type IPSECKEY struct {
Hdr RR_Header
Precedence uint8
// GatewayType: 1: A record, 2: AAAA record, 3: domainname.
// 0 is use for no type and GatewayName should be "." then.
GatewayType uint8
Algorithm uint8
Gateway string `dns:"ipseckey"`
// Gateway can be an A record, AAAA record or a domain name.
GatewayA net.IP `dns:"a"`
GatewayAAAA net.IP `dns:"aaaa"`
GatewayName string `dns:"domain-name"`
PublicKey string `dns:"base64"`
}
func (rr *IPSECKEY) Header() *RR_Header { return &rr.Hdr }
func (rr *IPSECKEY) copy() RR {
return &IPSECKEY{*rr.Hdr.copyHeader(), rr.Precedence, rr.GatewayType, rr.Algorithm, rr.Gateway, rr.PublicKey}
return &IPSECKEY{*rr.Hdr.copyHeader(), rr.Precedence, rr.GatewayType, rr.Algorithm, rr.GatewayA, rr.GatewayAAAA, rr.GatewayName, rr.PublicKey}
}
func (rr *IPSECKEY) String() string {
return rr.Hdr.String() + strconv.Itoa(int(rr.Precedence)) +
s := rr.Hdr.String() + strconv.Itoa(int(rr.Precedence)) +
" " + strconv.Itoa(int(rr.GatewayType)) +
" " + strconv.Itoa(int(rr.Algorithm)) +
" " + rr.Gateway +
" " + rr.PublicKey
" " + strconv.Itoa(int(rr.Algorithm))
switch rr.GatewayType {
case 0:
fallthrough
case 3:
s += " " + rr.GatewayName
case 1:
s += " " + rr.GatewayA.String()
case 2:
s += " " + rr.GatewayAAAA.String()
default:
s += " ."
}
s += " " + rr.PublicKey
return s
}
func (rr *IPSECKEY) len() int {
return rr.Hdr.len() + 3 + len(rr.Gateway) + 1 +
base64.StdEncoding.DecodedLen(len(rr.PublicKey))
l := rr.Hdr.len() + 3 + 1
switch rr.GatewayType {
default:
fallthrough
case 0:
fallthrough
case 3:
l += len(rr.GatewayName)
case 1:
l += 4
case 2:
l += 16
}
return l + base64.StdEncoding.DecodedLen(len(rr.PublicKey))
}
type KEY struct {
@ -1649,6 +1678,7 @@ var typeToRR = map[uint16]func() RR{
TypeEID: func() RR { return new(EID) },
TypeHINFO: func() RR { return new(HINFO) },
TypeHIP: func() RR { return new(HIP) },
TypeIPSECKEY: func() RR { return new(IPSECKEY) },
TypeKX: func() RR { return new(KX) },
TypeL32: func() RR { return new(L32) },
TypeL64: func() RR { return new(L64) },

View File

@ -1847,44 +1847,6 @@ func setURI(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
return rr, nil, c1
}
func setIPSECKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(IPSECKEY)
rr.Hdr = h
l := <-c
if l.length == 0 {
return rr, nil, l.comment
}
if i, e := strconv.Atoi(l.token); e != nil {
return nil, &ParseError{f, "bad IPSECKEY Precedence", l}, ""
} else {
rr.Precedence = uint8(i)
}
<-c // _BLANK
l = <-c
if i, e := strconv.Atoi(l.token); e != nil {
return nil, &ParseError{f, "bad IPSECKEY GatewayType", l}, ""
} else {
rr.GatewayType = uint8(i)
}
<-c // _BLANK
l = <-c
if i, e := strconv.Atoi(l.token); e != nil {
return nil, &ParseError{f, "bad IPSECKEY Algorithm", l}, ""
} else {
rr.Algorithm = uint8(i)
}
<-c
l = <-c
rr.Gateway = l.token
s, e, c1 := endingToString(c, "bad IPSECKEY PublicKey", f)
if e != nil {
return nil, e, c1
}
rr.PublicKey = s
return rr, nil, c1
}
func setDHCID(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
// awesome record to parse!
rr := new(DHCID)
@ -2087,6 +2049,73 @@ func setPX(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
return rr, nil, ""
}
func setIPSECKEY(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) {
rr := new(IPSECKEY)
rr.Hdr = h
l := <-c
if l.length == 0 {
return rr, nil, l.comment
}
if i, err := strconv.Atoi(l.token); err != nil {
return nil, &ParseError{f, "bad IPSECKEY Precedence", l}, ""
} else {
rr.Precedence = uint8(i)
}
<-c // _BLANK
l = <-c
if i, err := strconv.Atoi(l.token); err != nil {
return nil, &ParseError{f, "bad IPSECKEY GatewayType", l}, ""
} else {
rr.GatewayType = uint8(i)
}
<-c // _BLANK
l = <-c
if i, err := strconv.Atoi(l.token); err != nil {
return nil, &ParseError{f, "bad IPSECKEY Algorithm", l}, ""
} else {
rr.Algorithm = uint8(i)
}
// Now according to GatewayType we can have different elements here
<-c // _BLANK
l = <-c
switch rr.GatewayType {
case 0:
fallthrough
case 3:
rr.GatewayName = l.token
if l.token == "@" {
rr.GatewayName = o
}
_, ok := IsDomainName(l.token)
if !ok {
return nil, &ParseError{f, "bad IPSECKEY GatewayName", l}, ""
}
if rr.GatewayName[l.length-1] != '.' {
rr.GatewayName = appendOrigin(rr.GatewayName, o)
}
case 1:
rr.GatewayA = net.ParseIP(l.token)
if rr.GatewayA == nil {
return nil, &ParseError{f, "bad IPSECKEY GatewayA", l}, ""
}
case 2:
rr.GatewayAAAA = net.ParseIP(l.token)
if rr.GatewayAAAA == nil {
return nil, &ParseError{f, "bad IPSECKEY GatewayAAAA", l}, ""
}
default:
return nil, &ParseError{f, "bad IPSECKEY GatewayType", l}, ""
}
s, e, c1 := endingToString(c, "bad IPSECKEY PublicKey", f)
if e != nil {
return nil, e, c1
}
rr.PublicKey = s
return rr, nil, c1
}
var typeToparserFunc = map[uint16]parserFunc{
TypeAAAA: parserFunc{setAAAA, false},
TypeAFSDB: parserFunc{setAFSDB, false},