open-nomad/vendor/github.com/miekg/dns/scan_rr.go
Seth Hoenig 435c0d9fc8 deps: Switch to Go modules for dependency management
This PR switches the Nomad repository from using govendor to Go modules
for managing dependencies. Aspects of the Nomad workflow remain pretty
much the same. The usual Makefile targets should continue to work as
they always did. The API submodule simply defers to the parent Nomad
version on the repository, keeping the semantics of API versioning that
currently exists.
2020-06-02 14:30:36 -05:00

1699 lines
38 KiB
Go

package dns
import (
"encoding/base64"
"net"
"strconv"
"strings"
)
// A remainder of the rdata with embedded spaces, return the parsed string (sans the spaces)
// or an error
func endingToString(c *zlexer, errstr string) (string, *ParseError) {
var s string
l, _ := c.Next() // zString
for l.value != zNewline && l.value != zEOF {
if l.err {
return s, &ParseError{"", errstr, l}
}
switch l.value {
case zString:
s += l.token
case zBlank: // Ok
default:
return "", &ParseError{"", errstr, l}
}
l, _ = c.Next()
}
return s, nil
}
// A remainder of the rdata with embedded spaces, split on unquoted whitespace
// and return the parsed string slice or an error
func endingToTxtSlice(c *zlexer, errstr string) ([]string, *ParseError) {
// Get the remaining data until we see a zNewline
l, _ := c.Next()
if l.err {
return nil, &ParseError{"", errstr, l}
}
// Build the slice
s := make([]string, 0)
quote := false
empty := false
for l.value != zNewline && l.value != zEOF {
if l.err {
return nil, &ParseError{"", errstr, l}
}
switch l.value {
case zString:
empty = false
if len(l.token) > 255 {
// split up tokens that are larger than 255 into 255-chunks
sx := []string{}
p, i := 0, 255
for {
if i <= len(l.token) {
sx = append(sx, l.token[p:i])
} else {
sx = append(sx, l.token[p:])
break
}
p, i = p+255, i+255
}
s = append(s, sx...)
break
}
s = append(s, l.token)
case zBlank:
if quote {
// zBlank can only be seen in between txt parts.
return nil, &ParseError{"", errstr, l}
}
case zQuote:
if empty && quote {
s = append(s, "")
}
quote = !quote
empty = true
default:
return nil, &ParseError{"", errstr, l}
}
l, _ = c.Next()
}
if quote {
return nil, &ParseError{"", errstr, l}
}
return s, nil
}
func (rr *A) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
rr.A = net.ParseIP(l.token)
// IPv4 addresses cannot include ":".
// We do this rather than use net.IP's To4() because
// To4() treats IPv4-mapped IPv6 addresses as being
// IPv4.
isIPv4 := !strings.Contains(l.token, ":")
if rr.A == nil || !isIPv4 || l.err {
return &ParseError{"", "bad A A", l}
}
return slurpRemainder(c)
}
func (rr *AAAA) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
rr.AAAA = net.ParseIP(l.token)
// IPv6 addresses must include ":", and IPv4
// addresses cannot include ":".
isIPv6 := strings.Contains(l.token, ":")
if rr.AAAA == nil || !isIPv6 || l.err {
return &ParseError{"", "bad AAAA AAAA", l}
}
return slurpRemainder(c)
}
func (rr *NS) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad NS Ns", l}
}
rr.Ns = name
return slurpRemainder(c)
}
func (rr *PTR) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad PTR Ptr", l}
}
rr.Ptr = name
return slurpRemainder(c)
}
func (rr *NSAPPTR) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad NSAP-PTR Ptr", l}
}
rr.Ptr = name
return slurpRemainder(c)
}
func (rr *RP) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
mbox, mboxOk := toAbsoluteName(l.token, o)
if l.err || !mboxOk {
return &ParseError{"", "bad RP Mbox", l}
}
rr.Mbox = mbox
c.Next() // zBlank
l, _ = c.Next()
rr.Txt = l.token
txt, txtOk := toAbsoluteName(l.token, o)
if l.err || !txtOk {
return &ParseError{"", "bad RP Txt", l}
}
rr.Txt = txt
return slurpRemainder(c)
}
func (rr *MR) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad MR Mr", l}
}
rr.Mr = name
return slurpRemainder(c)
}
func (rr *MB) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad MB Mb", l}
}
rr.Mb = name
return slurpRemainder(c)
}
func (rr *MG) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad MG Mg", l}
}
rr.Mg = name
return slurpRemainder(c)
}
func (rr *HINFO) parse(c *zlexer, o string) *ParseError {
chunks, e := endingToTxtSlice(c, "bad HINFO Fields")
if e != nil {
return e
}
if ln := len(chunks); ln == 0 {
return nil
} else if ln == 1 {
// Can we split it?
if out := strings.Fields(chunks[0]); len(out) > 1 {
chunks = out
} else {
chunks = append(chunks, "")
}
}
rr.Cpu = chunks[0]
rr.Os = strings.Join(chunks[1:], " ")
return nil
}
func (rr *MINFO) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
rmail, rmailOk := toAbsoluteName(l.token, o)
if l.err || !rmailOk {
return &ParseError{"", "bad MINFO Rmail", l}
}
rr.Rmail = rmail
c.Next() // zBlank
l, _ = c.Next()
rr.Email = l.token
email, emailOk := toAbsoluteName(l.token, o)
if l.err || !emailOk {
return &ParseError{"", "bad MINFO Email", l}
}
rr.Email = email
return slurpRemainder(c)
}
func (rr *MF) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad MF Mf", l}
}
rr.Mf = name
return slurpRemainder(c)
}
func (rr *MD) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad MD Md", l}
}
rr.Md = name
return slurpRemainder(c)
}
func (rr *MX) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad MX Pref", l}
}
rr.Preference = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
rr.Mx = l.token
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad MX Mx", l}
}
rr.Mx = name
return slurpRemainder(c)
}
func (rr *RT) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil {
return &ParseError{"", "bad RT Preference", l}
}
rr.Preference = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
rr.Host = l.token
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad RT Host", l}
}
rr.Host = name
return slurpRemainder(c)
}
func (rr *AFSDB) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad AFSDB Subtype", l}
}
rr.Subtype = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
rr.Hostname = l.token
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad AFSDB Hostname", l}
}
rr.Hostname = name
return slurpRemainder(c)
}
func (rr *X25) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
if l.err {
return &ParseError{"", "bad X25 PSDNAddress", l}
}
rr.PSDNAddress = l.token
return slurpRemainder(c)
}
func (rr *KX) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad KX Pref", l}
}
rr.Preference = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
rr.Exchanger = l.token
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad KX Exchanger", l}
}
rr.Exchanger = name
return slurpRemainder(c)
}
func (rr *CNAME) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad CNAME Target", l}
}
rr.Target = name
return slurpRemainder(c)
}
func (rr *DNAME) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad DNAME Target", l}
}
rr.Target = name
return slurpRemainder(c)
}
func (rr *SOA) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
ns, nsOk := toAbsoluteName(l.token, o)
if l.err || !nsOk {
return &ParseError{"", "bad SOA Ns", l}
}
rr.Ns = ns
c.Next() // zBlank
l, _ = c.Next()
rr.Mbox = l.token
mbox, mboxOk := toAbsoluteName(l.token, o)
if l.err || !mboxOk {
return &ParseError{"", "bad SOA Mbox", l}
}
rr.Mbox = mbox
c.Next() // zBlank
var (
v uint32
ok bool
)
for i := 0; i < 5; i++ {
l, _ = c.Next()
if l.err {
return &ParseError{"", "bad SOA zone parameter", l}
}
if j, e := strconv.ParseUint(l.token, 10, 32); e != nil {
if i == 0 {
// Serial must be a number
return &ParseError{"", "bad SOA zone parameter", l}
}
// We allow other fields to be unitful duration strings
if v, ok = stringToTTL(l.token); !ok {
return &ParseError{"", "bad SOA zone parameter", l}
}
} else {
v = uint32(j)
}
switch i {
case 0:
rr.Serial = v
c.Next() // zBlank
case 1:
rr.Refresh = v
c.Next() // zBlank
case 2:
rr.Retry = v
c.Next() // zBlank
case 3:
rr.Expire = v
c.Next() // zBlank
case 4:
rr.Minttl = v
}
}
return slurpRemainder(c)
}
func (rr *SRV) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad SRV Priority", l}
}
rr.Priority = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
i, e = strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad SRV Weight", l}
}
rr.Weight = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
i, e = strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad SRV Port", l}
}
rr.Port = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
rr.Target = l.token
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad SRV Target", l}
}
rr.Target = name
return slurpRemainder(c)
}
func (rr *NAPTR) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad NAPTR Order", l}
}
rr.Order = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
i, e = strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad NAPTR Preference", l}
}
rr.Preference = uint16(i)
// Flags
c.Next() // zBlank
l, _ = c.Next() // _QUOTE
if l.value != zQuote {
return &ParseError{"", "bad NAPTR Flags", l}
}
l, _ = c.Next() // Either String or Quote
if l.value == zString {
rr.Flags = l.token
l, _ = c.Next() // _QUOTE
if l.value != zQuote {
return &ParseError{"", "bad NAPTR Flags", l}
}
} else if l.value == zQuote {
rr.Flags = ""
} else {
return &ParseError{"", "bad NAPTR Flags", l}
}
// Service
c.Next() // zBlank
l, _ = c.Next() // _QUOTE
if l.value != zQuote {
return &ParseError{"", "bad NAPTR Service", l}
}
l, _ = c.Next() // Either String or Quote
if l.value == zString {
rr.Service = l.token
l, _ = c.Next() // _QUOTE
if l.value != zQuote {
return &ParseError{"", "bad NAPTR Service", l}
}
} else if l.value == zQuote {
rr.Service = ""
} else {
return &ParseError{"", "bad NAPTR Service", l}
}
// Regexp
c.Next() // zBlank
l, _ = c.Next() // _QUOTE
if l.value != zQuote {
return &ParseError{"", "bad NAPTR Regexp", l}
}
l, _ = c.Next() // Either String or Quote
if l.value == zString {
rr.Regexp = l.token
l, _ = c.Next() // _QUOTE
if l.value != zQuote {
return &ParseError{"", "bad NAPTR Regexp", l}
}
} else if l.value == zQuote {
rr.Regexp = ""
} else {
return &ParseError{"", "bad NAPTR Regexp", l}
}
// After quote no space??
c.Next() // zBlank
l, _ = c.Next() // zString
rr.Replacement = l.token
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad NAPTR Replacement", l}
}
rr.Replacement = name
return slurpRemainder(c)
}
func (rr *TALINK) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
previousName, previousNameOk := toAbsoluteName(l.token, o)
if l.err || !previousNameOk {
return &ParseError{"", "bad TALINK PreviousName", l}
}
rr.PreviousName = previousName
c.Next() // zBlank
l, _ = c.Next()
rr.NextName = l.token
nextName, nextNameOk := toAbsoluteName(l.token, o)
if l.err || !nextNameOk {
return &ParseError{"", "bad TALINK NextName", l}
}
rr.NextName = nextName
return slurpRemainder(c)
}
func (rr *LOC) parse(c *zlexer, o string) *ParseError {
// Non zero defaults for LOC record, see RFC 1876, Section 3.
rr.HorizPre = 165 // 10000
rr.VertPre = 162 // 10
rr.Size = 18 // 1
ok := false
// North
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 32)
if e != nil || l.err {
return &ParseError{"", "bad LOC Latitude", l}
}
rr.Latitude = 1000 * 60 * 60 * uint32(i)
c.Next() // zBlank
// Either number, 'N' or 'S'
l, _ = c.Next()
if rr.Latitude, ok = locCheckNorth(l.token, rr.Latitude); ok {
goto East
}
i, e = strconv.ParseUint(l.token, 10, 32)
if e != nil || l.err {
return &ParseError{"", "bad LOC Latitude minutes", l}
}
rr.Latitude += 1000 * 60 * uint32(i)
c.Next() // zBlank
l, _ = c.Next()
if i, e := strconv.ParseFloat(l.token, 32); e != nil || l.err {
return &ParseError{"", "bad LOC Latitude seconds", l}
} else {
rr.Latitude += uint32(1000 * i)
}
c.Next() // zBlank
// Either number, 'N' or 'S'
l, _ = c.Next()
if rr.Latitude, ok = locCheckNorth(l.token, rr.Latitude); ok {
goto East
}
// If still alive, flag an error
return &ParseError{"", "bad LOC Latitude North/South", l}
East:
// East
c.Next() // zBlank
l, _ = c.Next()
if i, e := strconv.ParseUint(l.token, 10, 32); e != nil || l.err {
return &ParseError{"", "bad LOC Longitude", l}
} else {
rr.Longitude = 1000 * 60 * 60 * uint32(i)
}
c.Next() // zBlank
// Either number, 'E' or 'W'
l, _ = c.Next()
if rr.Longitude, ok = locCheckEast(l.token, rr.Longitude); ok {
goto Altitude
}
if i, e := strconv.ParseUint(l.token, 10, 32); e != nil || l.err {
return &ParseError{"", "bad LOC Longitude minutes", l}
} else {
rr.Longitude += 1000 * 60 * uint32(i)
}
c.Next() // zBlank
l, _ = c.Next()
if i, e := strconv.ParseFloat(l.token, 32); e != nil || l.err {
return &ParseError{"", "bad LOC Longitude seconds", l}
} else {
rr.Longitude += uint32(1000 * i)
}
c.Next() // zBlank
// Either number, 'E' or 'W'
l, _ = c.Next()
if rr.Longitude, ok = locCheckEast(l.token, rr.Longitude); ok {
goto Altitude
}
// If still alive, flag an error
return &ParseError{"", "bad LOC Longitude East/West", l}
Altitude:
c.Next() // zBlank
l, _ = c.Next()
if len(l.token) == 0 || l.err {
return &ParseError{"", "bad LOC Altitude", l}
}
if l.token[len(l.token)-1] == 'M' || l.token[len(l.token)-1] == 'm' {
l.token = l.token[0 : len(l.token)-1]
}
if i, e := strconv.ParseFloat(l.token, 32); e != nil {
return &ParseError{"", "bad LOC Altitude", l}
} else {
rr.Altitude = uint32(i*100.0 + 10000000.0 + 0.5)
}
// And now optionally the other values
l, _ = c.Next()
count := 0
for l.value != zNewline && l.value != zEOF {
switch l.value {
case zString:
switch count {
case 0: // Size
e, m, ok := stringToCm(l.token)
if !ok {
return &ParseError{"", "bad LOC Size", l}
}
rr.Size = e&0x0f | m<<4&0xf0
case 1: // HorizPre
e, m, ok := stringToCm(l.token)
if !ok {
return &ParseError{"", "bad LOC HorizPre", l}
}
rr.HorizPre = e&0x0f | m<<4&0xf0
case 2: // VertPre
e, m, ok := stringToCm(l.token)
if !ok {
return &ParseError{"", "bad LOC VertPre", l}
}
rr.VertPre = e&0x0f | m<<4&0xf0
}
count++
case zBlank:
// Ok
default:
return &ParseError{"", "bad LOC Size, HorizPre or VertPre", l}
}
l, _ = c.Next()
}
return nil
}
func (rr *HIP) parse(c *zlexer, o string) *ParseError {
// HitLength is not represented
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return &ParseError{"", "bad HIP PublicKeyAlgorithm", l}
}
rr.PublicKeyAlgorithm = uint8(i)
c.Next() // zBlank
l, _ = c.Next() // zString
if len(l.token) == 0 || l.err {
return &ParseError{"", "bad HIP Hit", l}
}
rr.Hit = l.token // This can not contain spaces, see RFC 5205 Section 6.
rr.HitLength = uint8(len(rr.Hit)) / 2
c.Next() // zBlank
l, _ = c.Next() // zString
if len(l.token) == 0 || l.err {
return &ParseError{"", "bad HIP PublicKey", l}
}
rr.PublicKey = l.token // This cannot contain spaces
rr.PublicKeyLength = uint16(base64.StdEncoding.DecodedLen(len(rr.PublicKey)))
// RendezvousServers (if any)
l, _ = c.Next()
var xs []string
for l.value != zNewline && l.value != zEOF {
switch l.value {
case zString:
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad HIP RendezvousServers", l}
}
xs = append(xs, name)
case zBlank:
// Ok
default:
return &ParseError{"", "bad HIP RendezvousServers", l}
}
l, _ = c.Next()
}
rr.RendezvousServers = xs
return nil
}
func (rr *CERT) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
if v, ok := StringToCertType[l.token]; ok {
rr.Type = v
} else if i, e := strconv.ParseUint(l.token, 10, 16); e != nil {
return &ParseError{"", "bad CERT Type", l}
} else {
rr.Type = uint16(i)
}
c.Next() // zBlank
l, _ = c.Next() // zString
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad CERT KeyTag", l}
}
rr.KeyTag = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
if v, ok := StringToAlgorithm[l.token]; ok {
rr.Algorithm = v
} else if i, e := strconv.ParseUint(l.token, 10, 8); e != nil {
return &ParseError{"", "bad CERT Algorithm", l}
} else {
rr.Algorithm = uint8(i)
}
s, e1 := endingToString(c, "bad CERT Certificate")
if e1 != nil {
return e1
}
rr.Certificate = s
return nil
}
func (rr *OPENPGPKEY) parse(c *zlexer, o string) *ParseError {
s, e := endingToString(c, "bad OPENPGPKEY PublicKey")
if e != nil {
return e
}
rr.PublicKey = s
return nil
}
func (rr *CSYNC) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
j, e := strconv.ParseUint(l.token, 10, 32)
if e != nil {
// Serial must be a number
return &ParseError{"", "bad CSYNC serial", l}
}
rr.Serial = uint32(j)
c.Next() // zBlank
l, _ = c.Next()
j, e = strconv.ParseUint(l.token, 10, 16)
if e != nil {
// Serial must be a number
return &ParseError{"", "bad CSYNC flags", l}
}
rr.Flags = uint16(j)
rr.TypeBitMap = make([]uint16, 0)
var (
k uint16
ok bool
)
l, _ = c.Next()
for l.value != zNewline && l.value != zEOF {
switch l.value {
case zBlank:
// Ok
case zString:
tokenUpper := strings.ToUpper(l.token)
if k, ok = StringToType[tokenUpper]; !ok {
if k, ok = typeToInt(l.token); !ok {
return &ParseError{"", "bad CSYNC TypeBitMap", l}
}
}
rr.TypeBitMap = append(rr.TypeBitMap, k)
default:
return &ParseError{"", "bad CSYNC TypeBitMap", l}
}
l, _ = c.Next()
}
return nil
}
func (rr *SIG) parse(c *zlexer, o string) *ParseError {
return rr.RRSIG.parse(c, o)
}
func (rr *RRSIG) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
tokenUpper := strings.ToUpper(l.token)
if t, ok := StringToType[tokenUpper]; !ok {
if strings.HasPrefix(tokenUpper, "TYPE") {
t, ok = typeToInt(l.token)
if !ok {
return &ParseError{"", "bad RRSIG Typecovered", l}
}
rr.TypeCovered = t
} else {
return &ParseError{"", "bad RRSIG Typecovered", l}
}
} else {
rr.TypeCovered = t
}
c.Next() // zBlank
l, _ = c.Next()
i, err := strconv.ParseUint(l.token, 10, 8)
if err != nil || l.err {
return &ParseError{"", "bad RRSIG Algorithm", l}
}
rr.Algorithm = uint8(i)
c.Next() // zBlank
l, _ = c.Next()
i, err = strconv.ParseUint(l.token, 10, 8)
if err != nil || l.err {
return &ParseError{"", "bad RRSIG Labels", l}
}
rr.Labels = uint8(i)
c.Next() // zBlank
l, _ = c.Next()
i, err = strconv.ParseUint(l.token, 10, 32)
if err != nil || l.err {
return &ParseError{"", "bad RRSIG OrigTtl", l}
}
rr.OrigTtl = uint32(i)
c.Next() // zBlank
l, _ = c.Next()
if i, err := StringToTime(l.token); err != nil {
// Try to see if all numeric and use it as epoch
if i, err := strconv.ParseInt(l.token, 10, 64); err == nil {
// TODO(miek): error out on > MAX_UINT32, same below
rr.Expiration = uint32(i)
} else {
return &ParseError{"", "bad RRSIG Expiration", l}
}
} else {
rr.Expiration = i
}
c.Next() // zBlank
l, _ = c.Next()
if i, err := StringToTime(l.token); err != nil {
if i, err := strconv.ParseInt(l.token, 10, 64); err == nil {
rr.Inception = uint32(i)
} else {
return &ParseError{"", "bad RRSIG Inception", l}
}
} else {
rr.Inception = i
}
c.Next() // zBlank
l, _ = c.Next()
i, err = strconv.ParseUint(l.token, 10, 16)
if err != nil || l.err {
return &ParseError{"", "bad RRSIG KeyTag", l}
}
rr.KeyTag = uint16(i)
c.Next() // zBlank
l, _ = c.Next()
rr.SignerName = l.token
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad RRSIG SignerName", l}
}
rr.SignerName = name
s, e := endingToString(c, "bad RRSIG Signature")
if e != nil {
return e
}
rr.Signature = s
return nil
}
func (rr *NSEC) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad NSEC NextDomain", l}
}
rr.NextDomain = name
rr.TypeBitMap = make([]uint16, 0)
var (
k uint16
ok bool
)
l, _ = c.Next()
for l.value != zNewline && l.value != zEOF {
switch l.value {
case zBlank:
// Ok
case zString:
tokenUpper := strings.ToUpper(l.token)
if k, ok = StringToType[tokenUpper]; !ok {
if k, ok = typeToInt(l.token); !ok {
return &ParseError{"", "bad NSEC TypeBitMap", l}
}
}
rr.TypeBitMap = append(rr.TypeBitMap, k)
default:
return &ParseError{"", "bad NSEC TypeBitMap", l}
}
l, _ = c.Next()
}
return nil
}
func (rr *NSEC3) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return &ParseError{"", "bad NSEC3 Hash", l}
}
rr.Hash = uint8(i)
c.Next() // zBlank
l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return &ParseError{"", "bad NSEC3 Flags", l}
}
rr.Flags = uint8(i)
c.Next() // zBlank
l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad NSEC3 Iterations", l}
}
rr.Iterations = uint16(i)
c.Next()
l, _ = c.Next()
if len(l.token) == 0 || l.err {
return &ParseError{"", "bad NSEC3 Salt", l}
}
if l.token != "-" {
rr.SaltLength = uint8(len(l.token)) / 2
rr.Salt = l.token
}
c.Next()
l, _ = c.Next()
if len(l.token) == 0 || l.err {
return &ParseError{"", "bad NSEC3 NextDomain", l}
}
rr.HashLength = 20 // Fix for NSEC3 (sha1 160 bits)
rr.NextDomain = l.token
rr.TypeBitMap = make([]uint16, 0)
var (
k uint16
ok bool
)
l, _ = c.Next()
for l.value != zNewline && l.value != zEOF {
switch l.value {
case zBlank:
// Ok
case zString:
tokenUpper := strings.ToUpper(l.token)
if k, ok = StringToType[tokenUpper]; !ok {
if k, ok = typeToInt(l.token); !ok {
return &ParseError{"", "bad NSEC3 TypeBitMap", l}
}
}
rr.TypeBitMap = append(rr.TypeBitMap, k)
default:
return &ParseError{"", "bad NSEC3 TypeBitMap", l}
}
l, _ = c.Next()
}
return nil
}
func (rr *NSEC3PARAM) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return &ParseError{"", "bad NSEC3PARAM Hash", l}
}
rr.Hash = uint8(i)
c.Next() // zBlank
l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return &ParseError{"", "bad NSEC3PARAM Flags", l}
}
rr.Flags = uint8(i)
c.Next() // zBlank
l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad NSEC3PARAM Iterations", l}
}
rr.Iterations = uint16(i)
c.Next()
l, _ = c.Next()
if l.token != "-" {
rr.SaltLength = uint8(len(l.token))
rr.Salt = l.token
}
return slurpRemainder(c)
}
func (rr *EUI48) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
if len(l.token) != 17 || l.err {
return &ParseError{"", "bad EUI48 Address", l}
}
addr := make([]byte, 12)
dash := 0
for i := 0; i < 10; i += 2 {
addr[i] = l.token[i+dash]
addr[i+1] = l.token[i+1+dash]
dash++
if l.token[i+1+dash] != '-' {
return &ParseError{"", "bad EUI48 Address", l}
}
}
addr[10] = l.token[15]
addr[11] = l.token[16]
i, e := strconv.ParseUint(string(addr), 16, 48)
if e != nil {
return &ParseError{"", "bad EUI48 Address", l}
}
rr.Address = i
return slurpRemainder(c)
}
func (rr *EUI64) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
if len(l.token) != 23 || l.err {
return &ParseError{"", "bad EUI64 Address", l}
}
addr := make([]byte, 16)
dash := 0
for i := 0; i < 14; i += 2 {
addr[i] = l.token[i+dash]
addr[i+1] = l.token[i+1+dash]
dash++
if l.token[i+1+dash] != '-' {
return &ParseError{"", "bad EUI64 Address", l}
}
}
addr[14] = l.token[21]
addr[15] = l.token[22]
i, e := strconv.ParseUint(string(addr), 16, 64)
if e != nil {
return &ParseError{"", "bad EUI68 Address", l}
}
rr.Address = i
return slurpRemainder(c)
}
func (rr *SSHFP) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return &ParseError{"", "bad SSHFP Algorithm", l}
}
rr.Algorithm = uint8(i)
c.Next() // zBlank
l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return &ParseError{"", "bad SSHFP Type", l}
}
rr.Type = uint8(i)
c.Next() // zBlank
s, e1 := endingToString(c, "bad SSHFP Fingerprint")
if e1 != nil {
return e1
}
rr.FingerPrint = s
return nil
}
func (rr *DNSKEY) parseDNSKEY(c *zlexer, o, typ string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad " + typ + " Flags", l}
}
rr.Flags = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return &ParseError{"", "bad " + typ + " Protocol", l}
}
rr.Protocol = uint8(i)
c.Next() // zBlank
l, _ = c.Next() // zString
i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return &ParseError{"", "bad " + typ + " Algorithm", l}
}
rr.Algorithm = uint8(i)
s, e1 := endingToString(c, "bad "+typ+" PublicKey")
if e1 != nil {
return e1
}
rr.PublicKey = s
return nil
}
func (rr *DNSKEY) parse(c *zlexer, o string) *ParseError {
return rr.parseDNSKEY(c, o, "DNSKEY")
}
func (rr *KEY) parse(c *zlexer, o string) *ParseError {
return rr.parseDNSKEY(c, o, "KEY")
}
func (rr *CDNSKEY) parse(c *zlexer, o string) *ParseError {
return rr.parseDNSKEY(c, o, "CDNSKEY")
}
func (rr *RKEY) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad RKEY Flags", l}
}
rr.Flags = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return &ParseError{"", "bad RKEY Protocol", l}
}
rr.Protocol = uint8(i)
c.Next() // zBlank
l, _ = c.Next() // zString
i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return &ParseError{"", "bad RKEY Algorithm", l}
}
rr.Algorithm = uint8(i)
s, e1 := endingToString(c, "bad RKEY PublicKey")
if e1 != nil {
return e1
}
rr.PublicKey = s
return nil
}
func (rr *EID) parse(c *zlexer, o string) *ParseError {
s, e := endingToString(c, "bad EID Endpoint")
if e != nil {
return e
}
rr.Endpoint = s
return nil
}
func (rr *NIMLOC) parse(c *zlexer, o string) *ParseError {
s, e := endingToString(c, "bad NIMLOC Locator")
if e != nil {
return e
}
rr.Locator = s
return nil
}
func (rr *GPOS) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
_, e := strconv.ParseFloat(l.token, 64)
if e != nil || l.err {
return &ParseError{"", "bad GPOS Longitude", l}
}
rr.Longitude = l.token
c.Next() // zBlank
l, _ = c.Next()
_, e = strconv.ParseFloat(l.token, 64)
if e != nil || l.err {
return &ParseError{"", "bad GPOS Latitude", l}
}
rr.Latitude = l.token
c.Next() // zBlank
l, _ = c.Next()
_, e = strconv.ParseFloat(l.token, 64)
if e != nil || l.err {
return &ParseError{"", "bad GPOS Altitude", l}
}
rr.Altitude = l.token
return slurpRemainder(c)
}
func (rr *DS) parseDS(c *zlexer, o, typ string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad " + typ + " KeyTag", l}
}
rr.KeyTag = uint16(i)
c.Next() // zBlank
l, _ = c.Next()
if i, e = strconv.ParseUint(l.token, 10, 8); e != nil {
tokenUpper := strings.ToUpper(l.token)
i, ok := StringToAlgorithm[tokenUpper]
if !ok || l.err {
return &ParseError{"", "bad " + typ + " Algorithm", l}
}
rr.Algorithm = i
} else {
rr.Algorithm = uint8(i)
}
c.Next() // zBlank
l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return &ParseError{"", "bad " + typ + " DigestType", l}
}
rr.DigestType = uint8(i)
s, e1 := endingToString(c, "bad "+typ+" Digest")
if e1 != nil {
return e1
}
rr.Digest = s
return nil
}
func (rr *DS) parse(c *zlexer, o string) *ParseError {
return rr.parseDS(c, o, "DS")
}
func (rr *DLV) parse(c *zlexer, o string) *ParseError {
return rr.parseDS(c, o, "DLV")
}
func (rr *CDS) parse(c *zlexer, o string) *ParseError {
return rr.parseDS(c, o, "CDS")
}
func (rr *TA) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad TA KeyTag", l}
}
rr.KeyTag = uint16(i)
c.Next() // zBlank
l, _ = c.Next()
if i, e := strconv.ParseUint(l.token, 10, 8); e != nil {
tokenUpper := strings.ToUpper(l.token)
i, ok := StringToAlgorithm[tokenUpper]
if !ok || l.err {
return &ParseError{"", "bad TA Algorithm", l}
}
rr.Algorithm = i
} else {
rr.Algorithm = uint8(i)
}
c.Next() // zBlank
l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return &ParseError{"", "bad TA DigestType", l}
}
rr.DigestType = uint8(i)
s, err := endingToString(c, "bad TA Digest")
if err != nil {
return err
}
rr.Digest = s
return nil
}
func (rr *TLSA) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return &ParseError{"", "bad TLSA Usage", l}
}
rr.Usage = uint8(i)
c.Next() // zBlank
l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return &ParseError{"", "bad TLSA Selector", l}
}
rr.Selector = uint8(i)
c.Next() // zBlank
l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return &ParseError{"", "bad TLSA MatchingType", l}
}
rr.MatchingType = uint8(i)
// So this needs be e2 (i.e. different than e), because...??t
s, e2 := endingToString(c, "bad TLSA Certificate")
if e2 != nil {
return e2
}
rr.Certificate = s
return nil
}
func (rr *SMIMEA) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return &ParseError{"", "bad SMIMEA Usage", l}
}
rr.Usage = uint8(i)
c.Next() // zBlank
l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return &ParseError{"", "bad SMIMEA Selector", l}
}
rr.Selector = uint8(i)
c.Next() // zBlank
l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
return &ParseError{"", "bad SMIMEA MatchingType", l}
}
rr.MatchingType = uint8(i)
// So this needs be e2 (i.e. different than e), because...??t
s, e2 := endingToString(c, "bad SMIMEA Certificate")
if e2 != nil {
return e2
}
rr.Certificate = s
return nil
}
func (rr *RFC3597) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
if l.token != "\\#" {
return &ParseError{"", "bad RFC3597 Rdata", l}
}
c.Next() // zBlank
l, _ = c.Next()
rdlength, e := strconv.Atoi(l.token)
if e != nil || l.err {
return &ParseError{"", "bad RFC3597 Rdata ", l}
}
s, e1 := endingToString(c, "bad RFC3597 Rdata")
if e1 != nil {
return e1
}
if rdlength*2 != len(s) {
return &ParseError{"", "bad RFC3597 Rdata", l}
}
rr.Rdata = s
return nil
}
func (rr *SPF) parse(c *zlexer, o string) *ParseError {
s, e := endingToTxtSlice(c, "bad SPF Txt")
if e != nil {
return e
}
rr.Txt = s
return nil
}
func (rr *AVC) parse(c *zlexer, o string) *ParseError {
s, e := endingToTxtSlice(c, "bad AVC Txt")
if e != nil {
return e
}
rr.Txt = s
return nil
}
func (rr *TXT) parse(c *zlexer, o string) *ParseError {
// no zBlank reading here, because all this rdata is TXT
s, e := endingToTxtSlice(c, "bad TXT Txt")
if e != nil {
return e
}
rr.Txt = s
return nil
}
// identical to setTXT
func (rr *NINFO) parse(c *zlexer, o string) *ParseError {
s, e := endingToTxtSlice(c, "bad NINFO ZSData")
if e != nil {
return e
}
rr.ZSData = s
return nil
}
func (rr *URI) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad URI Priority", l}
}
rr.Priority = uint16(i)
c.Next() // zBlank
l, _ = c.Next()
i, e = strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad URI Weight", l}
}
rr.Weight = uint16(i)
c.Next() // zBlank
s, err := endingToTxtSlice(c, "bad URI Target")
if err != nil {
return err
}
if len(s) != 1 {
return &ParseError{"", "bad URI Target", l}
}
rr.Target = s[0]
return nil
}
func (rr *DHCID) parse(c *zlexer, o string) *ParseError {
// awesome record to parse!
s, e := endingToString(c, "bad DHCID Digest")
if e != nil {
return e
}
rr.Digest = s
return nil
}
func (rr *NID) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad NID Preference", l}
}
rr.Preference = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
u, err := stringToNodeID(l)
if err != nil || l.err {
return err
}
rr.NodeID = u
return slurpRemainder(c)
}
func (rr *L32) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad L32 Preference", l}
}
rr.Preference = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
rr.Locator32 = net.ParseIP(l.token)
if rr.Locator32 == nil || l.err {
return &ParseError{"", "bad L32 Locator", l}
}
return slurpRemainder(c)
}
func (rr *LP) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad LP Preference", l}
}
rr.Preference = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
rr.Fqdn = l.token
name, nameOk := toAbsoluteName(l.token, o)
if l.err || !nameOk {
return &ParseError{"", "bad LP Fqdn", l}
}
rr.Fqdn = name
return slurpRemainder(c)
}
func (rr *L64) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad L64 Preference", l}
}
rr.Preference = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
u, err := stringToNodeID(l)
if err != nil || l.err {
return err
}
rr.Locator64 = u
return slurpRemainder(c)
}
func (rr *UID) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 32)
if e != nil || l.err {
return &ParseError{"", "bad UID Uid", l}
}
rr.Uid = uint32(i)
return slurpRemainder(c)
}
func (rr *GID) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 32)
if e != nil || l.err {
return &ParseError{"", "bad GID Gid", l}
}
rr.Gid = uint32(i)
return slurpRemainder(c)
}
func (rr *UINFO) parse(c *zlexer, o string) *ParseError {
s, e := endingToTxtSlice(c, "bad UINFO Uinfo")
if e != nil {
return e
}
if ln := len(s); ln == 0 {
return nil
}
rr.Uinfo = s[0] // silently discard anything after the first character-string
return nil
}
func (rr *PX) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, e := strconv.ParseUint(l.token, 10, 16)
if e != nil || l.err {
return &ParseError{"", "bad PX Preference", l}
}
rr.Preference = uint16(i)
c.Next() // zBlank
l, _ = c.Next() // zString
rr.Map822 = l.token
map822, map822Ok := toAbsoluteName(l.token, o)
if l.err || !map822Ok {
return &ParseError{"", "bad PX Map822", l}
}
rr.Map822 = map822
c.Next() // zBlank
l, _ = c.Next() // zString
rr.Mapx400 = l.token
mapx400, mapx400Ok := toAbsoluteName(l.token, o)
if l.err || !mapx400Ok {
return &ParseError{"", "bad PX Mapx400", l}
}
rr.Mapx400 = mapx400
return slurpRemainder(c)
}
func (rr *CAA) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
i, err := strconv.ParseUint(l.token, 10, 8)
if err != nil || l.err {
return &ParseError{"", "bad CAA Flag", l}
}
rr.Flag = uint8(i)
c.Next() // zBlank
l, _ = c.Next() // zString
if l.value != zString {
return &ParseError{"", "bad CAA Tag", l}
}
rr.Tag = l.token
c.Next() // zBlank
s, e := endingToTxtSlice(c, "bad CAA Value")
if e != nil {
return e
}
if len(s) != 1 {
return &ParseError{"", "bad CAA Value", l}
}
rr.Value = s[0]
return nil
}
func (rr *TKEY) parse(c *zlexer, o string) *ParseError {
l, _ := c.Next()
// Algorithm
if l.value != zString {
return &ParseError{"", "bad TKEY algorithm", l}
}
rr.Algorithm = l.token
c.Next() // zBlank
// Get the key length and key values
l, _ = c.Next()
i, err := strconv.ParseUint(l.token, 10, 8)
if err != nil || l.err {
return &ParseError{"", "bad TKEY key length", l}
}
rr.KeySize = uint16(i)
c.Next() // zBlank
l, _ = c.Next()
if l.value != zString {
return &ParseError{"", "bad TKEY key", l}
}
rr.Key = l.token
c.Next() // zBlank
// Get the otherdata length and string data
l, _ = c.Next()
i, err = strconv.ParseUint(l.token, 10, 8)
if err != nil || l.err {
return &ParseError{"", "bad TKEY otherdata length", l}
}
rr.OtherLen = uint16(i)
c.Next() // zBlank
l, _ = c.Next()
if l.value != zString {
return &ParseError{"", "bad TKEY otherday", l}
}
rr.OtherData = l.token
return nil
}