From 495b7d65529f4d80f4f48fe285e23459dd75289c Mon Sep 17 00:00:00 2001 From: Miek Gieben Date: Tue, 30 Apr 2013 16:42:04 +0200 Subject: [PATCH] Add UID/GID/UINFO record --- TODO.markdown | 2 +- msg.go | 8 ++++---- parse_test.go | 19 ++++++++++++++++++ types.go | 55 +++++++++++++++++++++++++++++++++++---------------- zscan_rr.go | 48 ++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 108 insertions(+), 24 deletions(-) diff --git a/TODO.markdown b/TODO.markdown index 0dd30274..4344d367 100644 --- a/TODO.markdown +++ b/TODO.markdown @@ -28,4 +28,4 @@ ATMA A6 KEY SIG -(maybe more) +NXT diff --git a/msg.go b/msg.go index 92b953c7..381eb429 100644 --- a/msg.go +++ b/msg.go @@ -129,10 +129,10 @@ var TypeToString = map[uint16]string{ TypeL32: "L32", TypeL64: "L64", TypeLP: "LP", - TypeUINFO: "UINFO", // lost in history - TypeUID: "UID", // " - TypeGID: "GID", // " - TypeUNSPEC: "UNSPEC", // " + TypeUINFO: "UINFO", + TypeUID: "UID", + TypeGID: "GID", + TypeUNSPEC: "UNSPEC", TypeEUI48: "EUI48", TypeEUI64: "EUI64", TypeTKEY: "TKEY", // Meta RR diff --git a/parse_test.go b/parse_test.go index a40f5cfc..427c80d6 100644 --- a/parse_test.go +++ b/parse_test.go @@ -756,3 +756,22 @@ func TestEUIxx(t *testing.T) { } } } + +func TestUserRR(t *testing.T) { + tests := map[string]string{ + "host.example. IN UID 1234": "host.example.\t3600\tIN\tUID\t1234", + "host.example. IN GID 1234556": "host.example.\t3600\tIN\tGID\t1234556", + "host.example. IN UINFO \"Miek Gieben\"": "host.example.\t3600\tIN\tUINFO\t\"Miek Gieben\"", + } + for i, o := range tests { + r, e := NewRR(i) + if e != nil { + t.Logf("Failed to parse %s: %s\n", i, e.Error()) + t.Fail() + } + if r.String() != o { + t.Logf("Want %s, got %s\n", o, r.String()) + t.Fail() + } + } +} diff --git a/types.go b/types.go index 3bfb05b2..f78b2ef6 100644 --- a/types.go +++ b/types.go @@ -651,14 +651,8 @@ type A struct { func (rr *A) Header() *RR_Header { return &rr.Hdr } func (rr *A) copy() RR { return &A{*rr.Hdr.copyHeader(), rr.A} } - -func (rr *A) String() string { - return rr.Hdr.String() + rr.A.String() -} - -func (rr *A) len() int { - return rr.Hdr.len() + net.IPv4len -} +func (rr *A) String() string { return rr.Hdr.String() + rr.A.String() } +func (rr *A) len() int { return rr.Hdr.len() + net.IPv4len } type AAAA struct { Hdr RR_Header @@ -667,14 +661,8 @@ type AAAA struct { func (rr *AAAA) Header() *RR_Header { return &rr.Hdr } func (rr *AAAA) copy() RR { return &AAAA{*rr.Hdr.copyHeader(), rr.AAAA} } - -func (rr *AAAA) String() string { - return rr.Hdr.String() + rr.AAAA.String() -} - -func (rr *AAAA) len() int { - return rr.Hdr.len() + net.IPv6len -} +func (rr *AAAA) String() string { return rr.Hdr.String() + rr.AAAA.String() } +func (rr *AAAA) len() int { return rr.Hdr.len() + net.IPv6len } type LOC struct { Hdr RR_Header @@ -890,7 +878,7 @@ func (rr *KX) String() string { } func (rr *KX) len() int { - return 0 + return rr.Hdr.len() + 2 + len(rr.Exchanger) } type TA struct { @@ -1442,6 +1430,36 @@ func (rr *CAA) len() int { return l } +type UID struct { + Hdr RR_Header + Uid uint32 +} + +func (rr *UID) Header() *RR_Header { return &rr.Hdr } +func (rr *UID) copy() RR { return &UID{*rr.Hdr.copyHeader(), rr.Uid} } +func (rr *UID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Uid), 10) } +func (rr *UID) len() int { return rr.Hdr.len() + 4 } + +type GID struct { + Hdr RR_Header + Gid uint32 +} + +func (rr *GID) Header() *RR_Header { return &rr.Hdr } +func (rr *GID) copy() RR { return &GID{*rr.Hdr.copyHeader(), rr.Gid} } +func (rr *GID) String() string { return rr.Hdr.String() + strconv.FormatInt(int64(rr.Gid), 10) } +func (rr *GID) len() int { return rr.Hdr.len() + 4 } + +type UINFO struct { + Hdr RR_Header + Uinfo string +} + +func (rr *UINFO) Header() *RR_Header { return &rr.Hdr } +func (rr *UINFO) copy() RR { return &UINFO{*rr.Hdr.copyHeader(), rr.Uinfo} } +func (rr *UINFO) String() string { return rr.Hdr.String() + strconv.QuoteToASCII(rr.Uinfo) } +func (rr *UINFO) len() int { return rr.Hdr.len() + len(rr.Uinfo) } + // TimeToString translates the RRSIG's incep. and expir. times to the // string representation used when printing the record. // It takes serial arithmetic (RFC 1982) into account. @@ -1565,4 +1583,7 @@ var rr_mk = map[uint16]func() RR{ TypeEUI48: func() RR { return new(EUI48) }, TypeEUI64: func() RR { return new(EUI64) }, TypeCAA: func() RR { return new(CAA) }, + TypeUID: func() RR { return new(UID) }, + TypeGID: func() RR { return new(GID) }, + TypeUINFO: func() RR { return new(UINFO) }, } diff --git a/zscan_rr.go b/zscan_rr.go index a1c46335..8f2f1d39 100644 --- a/zscan_rr.go +++ b/zscan_rr.go @@ -106,6 +106,15 @@ func setRR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { case TypeEUI64: r, e = setEUI64(h, c, f) goto Slurp + case TypeUID: + r, e = setUID(h, c, f) + goto Slurp + case TypeGID: + r, e = setGID(h, c, f) + goto Slurp + case TypeLOC: + r, e = setLOC(h, c, 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. @@ -145,8 +154,8 @@ func setRR(h RR_Header, c chan lex, o, f string) (RR, *ParseError, string) { return setDHCID(h, c, f) case TypeIPSECKEY: return setIPSECKEY(h, c, o, f) - case TypeLOC: - r, e = setLOC(h, c, f) + case TypeUINFO: + return setUINFO(h, c, f) default: // RFC3957 RR (Unknown RR handling) return setRFC3597(h, c, f) @@ -1871,3 +1880,38 @@ func setL64(h RR_Header, c chan lex, f string) (RR, *ParseError) { rr.Locator64 = u return rr, nil } + +func setUID(h RR_Header, c chan lex, f string) (RR, *ParseError) { + rr := new(UID) + rr.Hdr = h + l := <-c + if i, e := strconv.Atoi(l.token); e != nil { + return nil, &ParseError{f, "bad UID Uid", l} + } else { + rr.Uid = uint32(i) + } + return rr, nil +} + +func setGID(h RR_Header, c chan lex, f string) (RR, *ParseError) { + rr := new(GID) + rr.Hdr = h + l := <-c + if i, e := strconv.Atoi(l.token); e != nil { + return nil, &ParseError{f, "bad GID Gid", l} + } else { + rr.Gid = uint32(i) + } + return rr, nil +} + +func setUINFO(h RR_Header, c chan lex, f string) (RR, *ParseError, string) { + rr := new(UINFO) + rr.Hdr = h + s, e, c1 := endingToTxtSlice(c, "bad UINFO Uinfo", f) + if e != nil { + return nil, e, "" + } + rr.Uinfo = s[0] // silently discard anything above + return rr, nil, c1 +}