diff --git a/TODO.markdown b/TODO.markdown index 48bbb68e..d1e79e7d 100644 --- a/TODO.markdown +++ b/TODO.markdown @@ -8,15 +8,4 @@ * Speed, we can always go faster. A simple reflect server now hits 75/80K qps on moderate hardware * privatekey.Precompute() when signing? - -## RRs not implemented - -These are deprecated, or rarely used (or just a bitch to implement). - -PX -NIMLOC -ATMA -A6 -KEY -SIG -NXT +* Last remaining RRs: NIMLOC & EID, ATMA, A6, KEY, SIG and NXT diff --git a/msg.go b/msg.go index f0cb11a6..d378aeb1 100644 --- a/msg.go +++ b/msg.go @@ -141,6 +141,7 @@ var TypeToString = map[uint16]string{ TypeTLSA: "TLSA", TypeTSIG: "TSIG", // Meta RR TypeTXT: "TXT", + TypePX: "PX", TypeUID: "UID", TypeUINFO: "UINFO", TypeUNSPEC: "UNSPEC", diff --git a/parse_test.go b/parse_test.go index 9214e5cd..7623b421 100644 --- a/parse_test.go +++ b/parse_test.go @@ -615,6 +615,27 @@ func TestNSAPGPOS(t *testing.T) { } } +func TestPX(t *testing.T) { + dt := map[string]string{ + "*.net2.it. IN PX 10 net2.it. PRMD-net2.ADMD-p400.C-it.": "*.net2.it.\t3600\tIN\tPX\t10 net2.it. PRMD-net2.ADMD-p400.C-it.", + "ab.net2.it. IN PX 10 ab.net2.it. O-ab.PRMD-net2.ADMDb.C-it.": "ab.net2.it.\t3600\tIN\tPX\t10 ab.net2.it. O-ab.PRMD-net2.ADMDb.C-it.", + } + for i, o := range dt { + rr, e := NewRR(i) + if e != nil { + t.Log("Failed to parse RR: " + e.Error()) + t.Fail() + continue + } + if rr.String() != o { + t.Logf("`%s' should be equal to\n`%s', but is `%s'\n", i, o, rr.String()) + t.Fail() + } else { + t.Logf("RR is OK: `%s'", rr.String()) + } + } +} + func TestComment(t *testing.T) { // Comments we must see comments := map[string]bool{"; this is comment 1": true, diff --git a/types.go b/types.go index 39b66d6f..961caa4d 100644 --- a/types.go +++ b/types.go @@ -50,6 +50,7 @@ const ( TypeNSAPPTR uint16 = 23 TypeSIG uint16 = 24 TypeKEY uint16 = 25 + TypePX uint16 = 26 TypeGPOS uint16 = 27 TypeAAAA uint16 = 28 TypeLOC uint16 = 29 @@ -651,6 +652,20 @@ func (rr *AAAA) String() string { return rr.Hdr.String() + rr.AAAA.String() } +type PX struct { + Hdr RR_Header + Preference uint16 + Map822 string `dns:"domain-name"` + Mapx400 string `dns:"domain-name"` +} + +func (rr *PX) Header() *RR_Header { return &rr.Hdr } +func (rr *PX) copy() RR { return &PX{*rr.Hdr.copyHeader(), rr.Preference, rr.Map822, rr.Mapx400} } +func (rr *PX) String() string { + return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + " " + rr.Map822 + " " + rr.Mapx400 +} +func (rr *PX) len() int { return rr.Hdr.len() + 2 + len(rr.Map822) + len(rr.Mapx400) } + type GPOS struct { Hdr RR_Header Longitude string @@ -1585,6 +1600,7 @@ var rr_mk = map[uint16]func() RR{ TypePTR: func() RR { return new(PTR) }, TypeRKEY: func() RR { return new(RKEY) }, TypeRP: func() RR { return new(RP) }, + TypePX: func() RR { return new(PX) }, TypeRRSIG: func() RR { return new(RRSIG) }, TypeRT: func() RR { return new(RT) }, TypeSOA: func() RR { return new(SOA) }, diff --git a/zscan_rr.go b/zscan_rr.go index 0afc32d3..ce2022a4 100644 --- a/zscan_rr.go +++ b/zscan_rr.go @@ -128,6 +128,9 @@ func setRR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { case TypeGPOS: r, e = setGPOS(h, c, f) goto Slurp + case TypePX: + r, e = setPX(h, c, o, f) + goto Slurp // These types have a variable ending: either chunks of txt or chunks/base64 or hex. // They need to search for the end of the RR themselves, hence they look for the ending // newline. Thus there is no need to slurp the remainder, because there is none. @@ -1996,3 +1999,45 @@ func setUINFO(h RR_Header, c chan lex, f string) (RR, *ParseError, string) { rr.Uinfo = s[0] // silently discard anything above return rr, nil, c1 } + +func setPX(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { + rr := new(PX) + rr.Hdr = h + + l := <-c + if i, e := strconv.Atoi(l.token); e != nil { + return nil, &ParseError{f, "bad PX Preference", l} + } else { + rr.Preference = uint16(i) + } + <-c // _BLANK + l = <-c // _STRING + rr.Map822 = l.token + if l.token == "@" { + rr.Map822 = o + return rr, nil + } + _, ok := IsDomainName(l.token) + if !ok { + return nil, &ParseError{f, "bad PX Map822", l} + } + if rr.Map822[l.length-1] != '.' { + rr.Map822 = appendOrigin(rr.Map822, o) + } + <-c // _BLANK + l = <-c // _STRING + rr.Mapx400 = l.token + if l.token == "@" { + rr.Mapx400 = o + return rr, nil + } + _, ok = IsDomainName(l.token) + if !ok { + return nil, &ParseError{f, "bad PX Mapx400", l} + } + if rr.Mapx400[l.length-1] != '.' { + rr.Mapx400 = appendOrigin(rr.Mapx400, o) + } + return rr, nil +} +