From 314a0eebcc055a1b58d343a69d3cbc10f62f943b Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Sun, 18 Nov 2012 10:29:05 +0100 Subject: [PATCH] Add support for L32, NID, L64 and LP records --- parse_test.go | 28 +++++++++-------- types.go | 7 +++-- zscan.go | 18 +++++++++++ zscan_rr.go | 85 ++++++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 111 insertions(+), 27 deletions(-) diff --git a/parse_test.go b/parse_test.go index e2872004..ceedd4b4 100644 --- a/parse_test.go +++ b/parse_test.go @@ -637,25 +637,27 @@ func TestParseBackslash(t *testing.T) { func TestILNP(t *testing.T) { tests := []string{ - "host1.example.com. IN NID 10 0014:4fff:ff20:ee64", - "host1.example.com. IN NID 20 0015:5fff:ff21:ee65", - "host2.example.com. IN NID 10 0016:6fff:ff22:ee66", - "host1.example.com. IN L32 10 10.1.02.0", - "host1.example.com. IN L32 20 10.1.04.0", - "host2.example.com. IN L32 10 10.1.08.0", - "host1.example.com. IN L64 10 2001:0DB8:1140:1000", - "host1.example.com. IN L64 20 2001:0DB8:2140:2000", - "host2.example.com. IN L64 10 2001:0DB8:4140:4000", - "host1.example.com. IN LP 10 l64-subnet1.example.com.", - "host1.example.com. IN LP 10 l64-subnet2.example.com.", - "host1.example.com. IN LP 20 l32-subnet1.example.com.", + "host1.example.com.\t3600\tIN\tNID\t10 0014:4fff:ff20:ee64", + "host1.example.com.\t3600\tIN\tNID\t20 0015:5fff:ff21:ee65", + "host2.example.com.\t3600\tIN\tNID\t10 0016:6fff:ff22:ee66", + "host1.example.com.\t3600\tIN\tL32\t10 10.1.2.0", + "host1.example.com.\t3600\tIN\tL32\t20 10.1.4.0", + "host2.example.com.\t3600\tIN\tL32\t10 10.1.8.0", + "host1.example.com.\t3600\tIN\tL64\t10 2001:0DB8:1140:1000", + "host1.example.com.\t3600\tIN\tL64\t20 2001:0DB8:2140:2000", + "host2.example.com.\t3600\tIN\tL64\t10 2001:0DB8:4140:4000", + "host1.example.com.\t3600\tIN\tLP\t10 l64-subnet1.example.com.", + "host1.example.com.\t3600\tIN\tLP\t10 l64-subnet2.example.com.", + "host1.example.com.\t3600\tIN\tLP\t20 l32-subnet1.example.com.", } for _, t1 := range tests { r, e := NewRR(t1) if e != nil { t.Fatalf("An error occured: %s\n", e.Error()) } else { - t.Logf("%s\n", r.String()) + if t1 != r.String() { + t.Fatalf("Strings should be equal %s %s", t1, r.String()) + } } } } diff --git a/types.go b/types.go index 5c002c93..11aace9d 100644 --- a/types.go +++ b/types.go @@ -1388,7 +1388,7 @@ func (rr *RR_NID) Header() *RR_Header { func (rr *RR_NID) String() string { s := rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) node := fmt.Sprintf("%0.16x", rr.NodeID) - s += node[0:3] + ":" + node[4:7] + ":" + node[8:11] + ":" + node[12:15] + s += " " + node[0:4] + ":" + node[4:8] + ":" + node[8:12] + ":" + node[12:16] return s } @@ -1411,7 +1411,8 @@ func (rr *RR_L32) Header() *RR_Header { } func (rr *RR_L32) String() string { - return rr.Hdr.String() + rr.Locator32.String() + return rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) + + " " + rr.Locator32.String() } func (rr *RR_L32) Len() int { @@ -1435,7 +1436,7 @@ func (rr *RR_L64) Header() *RR_Header { func (rr *RR_L64) String() string { s := rr.Hdr.String() + strconv.Itoa(int(rr.Preference)) node := fmt.Sprintf("%0.16X", rr.Locator64) - s += node[0:3] + ":" + node[4:7] + ":" + node[8:11] + ":" + node[12:15] + s += " " + node[0:4] + ":" + node[4:8] + ":" + node[8:12] + ":" + node[12:16] return s } diff --git a/zscan.go b/zscan.go index 6e83ecae..c273374f 100644 --- a/zscan.go +++ b/zscan.go @@ -826,3 +826,21 @@ func slurpRemainder(c chan lex, f string) *ParseError { } return nil } + +// Parse a 64 bit-like ipv6 address: "0014:4fff:ff20:ee64" +// Used for NID and L64 record. +func stringToNodeID(l lex) (uint64, *ParseError) { + if len(l.token) < 19 { + return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l} + } + // There must be three colons at fixes postitions, if not its a parse error + if l.token[4] != ':' && l.token[9] != ':' && l.token[14] != ':' { + return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l} + } + s := l.token[0:4] + l.token[5:9] + l.token[10:14] + l.token[15:19] + u, e := strconv.ParseUint(s, 16,64) + if e != nil { + return 0, &ParseError{l.token, "bad NID/L64 NodeID/Locator64", l} + } + return u, nil +} diff --git a/zscan_rr.go b/zscan_rr.go index 7b431ea3..88235931 100644 --- a/zscan_rr.go +++ b/zscan_rr.go @@ -82,14 +82,14 @@ func setRR(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { case TypeKX: r, e = setKX(h, c, o, f) goto Slurp -// case TypeNID: -// r, e := setNID(h, c, f) + case TypeNID: + r, e = setNID(h, c, f) case TypeL32: r, e = setL32(h, c, f) -// case TypeL64: -// r, e := setL64(h, c, f) -// case TypeLP: -// r, e := setLP(h, c, o, f) + case TypeL64: + r, e = setL64(h, c, f) + case TypeLP: + r, e = setLP(h, c, o, f) // 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. @@ -392,7 +392,7 @@ func setMX(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { if i, e := strconv.Atoi(l.token); e != nil { return nil, &ParseError{f, "bad MX Pref", l} } else { - rr.Pref = uint16(i) + rr.Preference = uint16(i) } <-c // _BLANK l = <-c // _STRING @@ -473,7 +473,7 @@ func setKX(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { if i, e := strconv.Atoi(l.token); e != nil { return nil, &ParseError{f, "bad KX Pref", l} } else { - rr.Pref = uint16(i) + rr.Preference = uint16(i) } <-c // _BLANK l = <-c // _STRING @@ -660,7 +660,7 @@ func setNAPTR(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { if i, e := strconv.Atoi(l.token); e != nil { return nil, &ParseError{f, "bad NAPTR Preference", l} } else { - rr.Pref = uint16(i) + rr.Preference = uint16(i) } // Flags <-c // _BLANK @@ -1093,7 +1093,7 @@ func setNSEC(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { rr.TypeBitMap = make([]uint16, 0) var ( - k uint16 + k uint16 ok bool ) l = <-c @@ -1738,7 +1738,23 @@ func setDHCID(h RR_Header, c chan lex, f string) (RR, *ParseError) { } func setNID(h RR_Header, c chan lex, f string) (RR, *ParseError) { - return nil, nil + rr := new(RR_NID) + rr.Hdr = h + + l := <-c + if i, e := strconv.Atoi(l.token); e != nil { + return nil, &ParseError{f, "bad NID Preference", l} + } else { + rr.Preference = uint16(i) + } + <-c // _BLANK + l = <-c // _STRING + u, err := stringToNodeID(l) + if err != nil { + return nil, err + } + rr.NodeID = u + return rr, nil } func setL32(h RR_Header, c chan lex, f string) (RR, *ParseError) { @@ -1759,3 +1775,50 @@ func setL32(h RR_Header, c chan lex, f string) (RR, *ParseError) { } return rr, nil } + +func setLP(h RR_Header, c chan lex, o, f string) (RR, *ParseError) { + rr := new(RR_LP) + rr.Hdr = h + + l := <-c + if i, e := strconv.Atoi(l.token); e != nil { + return nil, &ParseError{f, "bad LP Preference", l} + } else { + rr.Preference = uint16(i) + } + <-c // _BLANK + l = <-c // _STRING + rr.Fqdn = l.token + if l.token == "@" { + rr.Fqdn = o + return rr, nil + } + _, ld, ok := IsDomainName(l.token) + if !ok { + return nil, &ParseError{f, "bad LP Fqdn", l} + } + if rr.Fqdn[ld-1] != '.' { + rr.Fqdn = appendOrigin(rr.Fqdn, o) + } + return rr, nil +} + +func setL64(h RR_Header, c chan lex, f string) (RR, *ParseError) { + rr := new(RR_L64) + rr.Hdr = h + + l := <-c + if i, e := strconv.Atoi(l.token); e != nil { + return nil, &ParseError{f, "bad L64 Preference", l} + } else { + rr.Preference = uint16(i) + } + <-c // _BLANK + l = <-c // _STRING + u, err := stringToNodeID(l) + if err != nil { + return nil, err + } + rr.Locator64 = u + return rr, nil +}