gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

scan_rr.go (44586B)


      1 package dns
      2 
      3 import (
      4 	"bytes"
      5 	"encoding/base64"
      6 	"errors"
      7 	"net"
      8 	"strconv"
      9 	"strings"
     10 )
     11 
     12 // A remainder of the rdata with embedded spaces, return the parsed string (sans the spaces)
     13 // or an error
     14 func endingToString(c *zlexer, errstr string) (string, *ParseError) {
     15 	var buffer bytes.Buffer
     16 	l, _ := c.Next() // zString
     17 	for l.value != zNewline && l.value != zEOF {
     18 		if l.err {
     19 			return buffer.String(), &ParseError{"", errstr, l}
     20 		}
     21 		switch l.value {
     22 		case zString:
     23 			buffer.WriteString(l.token)
     24 		case zBlank: // Ok
     25 		default:
     26 			return "", &ParseError{"", errstr, l}
     27 		}
     28 		l, _ = c.Next()
     29 	}
     30 
     31 	return buffer.String(), nil
     32 }
     33 
     34 // A remainder of the rdata with embedded spaces, split on unquoted whitespace
     35 // and return the parsed string slice or an error
     36 func endingToTxtSlice(c *zlexer, errstr string) ([]string, *ParseError) {
     37 	// Get the remaining data until we see a zNewline
     38 	l, _ := c.Next()
     39 	if l.err {
     40 		return nil, &ParseError{"", errstr, l}
     41 	}
     42 
     43 	// Build the slice
     44 	s := make([]string, 0)
     45 	quote := false
     46 	empty := false
     47 	for l.value != zNewline && l.value != zEOF {
     48 		if l.err {
     49 			return nil, &ParseError{"", errstr, l}
     50 		}
     51 		switch l.value {
     52 		case zString:
     53 			empty = false
     54 			if len(l.token) > 255 {
     55 				// split up tokens that are larger than 255 into 255-chunks
     56 				sx := []string{}
     57 				p, i := 0, 255
     58 				for {
     59 					if i <= len(l.token) {
     60 						sx = append(sx, l.token[p:i])
     61 					} else {
     62 						sx = append(sx, l.token[p:])
     63 						break
     64 
     65 					}
     66 					p, i = p+255, i+255
     67 				}
     68 				s = append(s, sx...)
     69 				break
     70 			}
     71 
     72 			s = append(s, l.token)
     73 		case zBlank:
     74 			if quote {
     75 				// zBlank can only be seen in between txt parts.
     76 				return nil, &ParseError{"", errstr, l}
     77 			}
     78 		case zQuote:
     79 			if empty && quote {
     80 				s = append(s, "")
     81 			}
     82 			quote = !quote
     83 			empty = true
     84 		default:
     85 			return nil, &ParseError{"", errstr, l}
     86 		}
     87 		l, _ = c.Next()
     88 	}
     89 
     90 	if quote {
     91 		return nil, &ParseError{"", errstr, l}
     92 	}
     93 
     94 	return s, nil
     95 }
     96 
     97 func (rr *A) parse(c *zlexer, o string) *ParseError {
     98 	l, _ := c.Next()
     99 	rr.A = net.ParseIP(l.token)
    100 	// IPv4 addresses cannot include ":".
    101 	// We do this rather than use net.IP's To4() because
    102 	// To4() treats IPv4-mapped IPv6 addresses as being
    103 	// IPv4.
    104 	isIPv4 := !strings.Contains(l.token, ":")
    105 	if rr.A == nil || !isIPv4 || l.err {
    106 		return &ParseError{"", "bad A A", l}
    107 	}
    108 	return slurpRemainder(c)
    109 }
    110 
    111 func (rr *AAAA) parse(c *zlexer, o string) *ParseError {
    112 	l, _ := c.Next()
    113 	rr.AAAA = net.ParseIP(l.token)
    114 	// IPv6 addresses must include ":", and IPv4
    115 	// addresses cannot include ":".
    116 	isIPv6 := strings.Contains(l.token, ":")
    117 	if rr.AAAA == nil || !isIPv6 || l.err {
    118 		return &ParseError{"", "bad AAAA AAAA", l}
    119 	}
    120 	return slurpRemainder(c)
    121 }
    122 
    123 func (rr *NS) parse(c *zlexer, o string) *ParseError {
    124 	l, _ := c.Next()
    125 	name, nameOk := toAbsoluteName(l.token, o)
    126 	if l.err || !nameOk {
    127 		return &ParseError{"", "bad NS Ns", l}
    128 	}
    129 	rr.Ns = name
    130 	return slurpRemainder(c)
    131 }
    132 
    133 func (rr *PTR) parse(c *zlexer, o string) *ParseError {
    134 	l, _ := c.Next()
    135 	name, nameOk := toAbsoluteName(l.token, o)
    136 	if l.err || !nameOk {
    137 		return &ParseError{"", "bad PTR Ptr", l}
    138 	}
    139 	rr.Ptr = name
    140 	return slurpRemainder(c)
    141 }
    142 
    143 func (rr *NSAPPTR) parse(c *zlexer, o string) *ParseError {
    144 	l, _ := c.Next()
    145 	name, nameOk := toAbsoluteName(l.token, o)
    146 	if l.err || !nameOk {
    147 		return &ParseError{"", "bad NSAP-PTR Ptr", l}
    148 	}
    149 	rr.Ptr = name
    150 	return slurpRemainder(c)
    151 }
    152 
    153 func (rr *RP) parse(c *zlexer, o string) *ParseError {
    154 	l, _ := c.Next()
    155 	mbox, mboxOk := toAbsoluteName(l.token, o)
    156 	if l.err || !mboxOk {
    157 		return &ParseError{"", "bad RP Mbox", l}
    158 	}
    159 	rr.Mbox = mbox
    160 
    161 	c.Next() // zBlank
    162 	l, _ = c.Next()
    163 	rr.Txt = l.token
    164 
    165 	txt, txtOk := toAbsoluteName(l.token, o)
    166 	if l.err || !txtOk {
    167 		return &ParseError{"", "bad RP Txt", l}
    168 	}
    169 	rr.Txt = txt
    170 
    171 	return slurpRemainder(c)
    172 }
    173 
    174 func (rr *MR) parse(c *zlexer, o string) *ParseError {
    175 	l, _ := c.Next()
    176 	name, nameOk := toAbsoluteName(l.token, o)
    177 	if l.err || !nameOk {
    178 		return &ParseError{"", "bad MR Mr", l}
    179 	}
    180 	rr.Mr = name
    181 	return slurpRemainder(c)
    182 }
    183 
    184 func (rr *MB) parse(c *zlexer, o string) *ParseError {
    185 	l, _ := c.Next()
    186 	name, nameOk := toAbsoluteName(l.token, o)
    187 	if l.err || !nameOk {
    188 		return &ParseError{"", "bad MB Mb", l}
    189 	}
    190 	rr.Mb = name
    191 	return slurpRemainder(c)
    192 }
    193 
    194 func (rr *MG) parse(c *zlexer, o string) *ParseError {
    195 	l, _ := c.Next()
    196 	name, nameOk := toAbsoluteName(l.token, o)
    197 	if l.err || !nameOk {
    198 		return &ParseError{"", "bad MG Mg", l}
    199 	}
    200 	rr.Mg = name
    201 	return slurpRemainder(c)
    202 }
    203 
    204 func (rr *HINFO) parse(c *zlexer, o string) *ParseError {
    205 	chunks, e := endingToTxtSlice(c, "bad HINFO Fields")
    206 	if e != nil {
    207 		return e
    208 	}
    209 
    210 	if ln := len(chunks); ln == 0 {
    211 		return nil
    212 	} else if ln == 1 {
    213 		// Can we split it?
    214 		if out := strings.Fields(chunks[0]); len(out) > 1 {
    215 			chunks = out
    216 		} else {
    217 			chunks = append(chunks, "")
    218 		}
    219 	}
    220 
    221 	rr.Cpu = chunks[0]
    222 	rr.Os = strings.Join(chunks[1:], " ")
    223 
    224 	return nil
    225 }
    226 
    227 func (rr *MINFO) parse(c *zlexer, o string) *ParseError {
    228 	l, _ := c.Next()
    229 	rmail, rmailOk := toAbsoluteName(l.token, o)
    230 	if l.err || !rmailOk {
    231 		return &ParseError{"", "bad MINFO Rmail", l}
    232 	}
    233 	rr.Rmail = rmail
    234 
    235 	c.Next() // zBlank
    236 	l, _ = c.Next()
    237 	rr.Email = l.token
    238 
    239 	email, emailOk := toAbsoluteName(l.token, o)
    240 	if l.err || !emailOk {
    241 		return &ParseError{"", "bad MINFO Email", l}
    242 	}
    243 	rr.Email = email
    244 
    245 	return slurpRemainder(c)
    246 }
    247 
    248 func (rr *MF) parse(c *zlexer, o string) *ParseError {
    249 	l, _ := c.Next()
    250 	name, nameOk := toAbsoluteName(l.token, o)
    251 	if l.err || !nameOk {
    252 		return &ParseError{"", "bad MF Mf", l}
    253 	}
    254 	rr.Mf = name
    255 	return slurpRemainder(c)
    256 }
    257 
    258 func (rr *MD) parse(c *zlexer, o string) *ParseError {
    259 	l, _ := c.Next()
    260 	name, nameOk := toAbsoluteName(l.token, o)
    261 	if l.err || !nameOk {
    262 		return &ParseError{"", "bad MD Md", l}
    263 	}
    264 	rr.Md = name
    265 	return slurpRemainder(c)
    266 }
    267 
    268 func (rr *MX) parse(c *zlexer, o string) *ParseError {
    269 	l, _ := c.Next()
    270 	i, e := strconv.ParseUint(l.token, 10, 16)
    271 	if e != nil || l.err {
    272 		return &ParseError{"", "bad MX Pref", l}
    273 	}
    274 	rr.Preference = uint16(i)
    275 
    276 	c.Next()        // zBlank
    277 	l, _ = c.Next() // zString
    278 	rr.Mx = l.token
    279 
    280 	name, nameOk := toAbsoluteName(l.token, o)
    281 	if l.err || !nameOk {
    282 		return &ParseError{"", "bad MX Mx", l}
    283 	}
    284 	rr.Mx = name
    285 
    286 	return slurpRemainder(c)
    287 }
    288 
    289 func (rr *RT) parse(c *zlexer, o string) *ParseError {
    290 	l, _ := c.Next()
    291 	i, e := strconv.ParseUint(l.token, 10, 16)
    292 	if e != nil {
    293 		return &ParseError{"", "bad RT Preference", l}
    294 	}
    295 	rr.Preference = uint16(i)
    296 
    297 	c.Next()        // zBlank
    298 	l, _ = c.Next() // zString
    299 	rr.Host = l.token
    300 
    301 	name, nameOk := toAbsoluteName(l.token, o)
    302 	if l.err || !nameOk {
    303 		return &ParseError{"", "bad RT Host", l}
    304 	}
    305 	rr.Host = name
    306 
    307 	return slurpRemainder(c)
    308 }
    309 
    310 func (rr *AFSDB) parse(c *zlexer, o string) *ParseError {
    311 	l, _ := c.Next()
    312 	i, e := strconv.ParseUint(l.token, 10, 16)
    313 	if e != nil || l.err {
    314 		return &ParseError{"", "bad AFSDB Subtype", l}
    315 	}
    316 	rr.Subtype = uint16(i)
    317 
    318 	c.Next()        // zBlank
    319 	l, _ = c.Next() // zString
    320 	rr.Hostname = l.token
    321 
    322 	name, nameOk := toAbsoluteName(l.token, o)
    323 	if l.err || !nameOk {
    324 		return &ParseError{"", "bad AFSDB Hostname", l}
    325 	}
    326 	rr.Hostname = name
    327 	return slurpRemainder(c)
    328 }
    329 
    330 func (rr *X25) parse(c *zlexer, o string) *ParseError {
    331 	l, _ := c.Next()
    332 	if l.err {
    333 		return &ParseError{"", "bad X25 PSDNAddress", l}
    334 	}
    335 	rr.PSDNAddress = l.token
    336 	return slurpRemainder(c)
    337 }
    338 
    339 func (rr *KX) parse(c *zlexer, o string) *ParseError {
    340 	l, _ := c.Next()
    341 	i, e := strconv.ParseUint(l.token, 10, 16)
    342 	if e != nil || l.err {
    343 		return &ParseError{"", "bad KX Pref", l}
    344 	}
    345 	rr.Preference = uint16(i)
    346 
    347 	c.Next()        // zBlank
    348 	l, _ = c.Next() // zString
    349 	rr.Exchanger = l.token
    350 
    351 	name, nameOk := toAbsoluteName(l.token, o)
    352 	if l.err || !nameOk {
    353 		return &ParseError{"", "bad KX Exchanger", l}
    354 	}
    355 	rr.Exchanger = name
    356 	return slurpRemainder(c)
    357 }
    358 
    359 func (rr *CNAME) parse(c *zlexer, o string) *ParseError {
    360 	l, _ := c.Next()
    361 	name, nameOk := toAbsoluteName(l.token, o)
    362 	if l.err || !nameOk {
    363 		return &ParseError{"", "bad CNAME Target", l}
    364 	}
    365 	rr.Target = name
    366 	return slurpRemainder(c)
    367 }
    368 
    369 func (rr *DNAME) parse(c *zlexer, o string) *ParseError {
    370 	l, _ := c.Next()
    371 	name, nameOk := toAbsoluteName(l.token, o)
    372 	if l.err || !nameOk {
    373 		return &ParseError{"", "bad DNAME Target", l}
    374 	}
    375 	rr.Target = name
    376 	return slurpRemainder(c)
    377 }
    378 
    379 func (rr *SOA) parse(c *zlexer, o string) *ParseError {
    380 	l, _ := c.Next()
    381 	ns, nsOk := toAbsoluteName(l.token, o)
    382 	if l.err || !nsOk {
    383 		return &ParseError{"", "bad SOA Ns", l}
    384 	}
    385 	rr.Ns = ns
    386 
    387 	c.Next() // zBlank
    388 	l, _ = c.Next()
    389 	rr.Mbox = l.token
    390 
    391 	mbox, mboxOk := toAbsoluteName(l.token, o)
    392 	if l.err || !mboxOk {
    393 		return &ParseError{"", "bad SOA Mbox", l}
    394 	}
    395 	rr.Mbox = mbox
    396 
    397 	c.Next() // zBlank
    398 
    399 	var (
    400 		v  uint32
    401 		ok bool
    402 	)
    403 	for i := 0; i < 5; i++ {
    404 		l, _ = c.Next()
    405 		if l.err {
    406 			return &ParseError{"", "bad SOA zone parameter", l}
    407 		}
    408 		if j, err := strconv.ParseUint(l.token, 10, 32); err != nil {
    409 			if i == 0 {
    410 				// Serial must be a number
    411 				return &ParseError{"", "bad SOA zone parameter", l}
    412 			}
    413 			// We allow other fields to be unitful duration strings
    414 			if v, ok = stringToTTL(l.token); !ok {
    415 				return &ParseError{"", "bad SOA zone parameter", l}
    416 
    417 			}
    418 		} else {
    419 			v = uint32(j)
    420 		}
    421 		switch i {
    422 		case 0:
    423 			rr.Serial = v
    424 			c.Next() // zBlank
    425 		case 1:
    426 			rr.Refresh = v
    427 			c.Next() // zBlank
    428 		case 2:
    429 			rr.Retry = v
    430 			c.Next() // zBlank
    431 		case 3:
    432 			rr.Expire = v
    433 			c.Next() // zBlank
    434 		case 4:
    435 			rr.Minttl = v
    436 		}
    437 	}
    438 	return slurpRemainder(c)
    439 }
    440 
    441 func (rr *SRV) parse(c *zlexer, o string) *ParseError {
    442 	l, _ := c.Next()
    443 	i, e := strconv.ParseUint(l.token, 10, 16)
    444 	if e != nil || l.err {
    445 		return &ParseError{"", "bad SRV Priority", l}
    446 	}
    447 	rr.Priority = uint16(i)
    448 
    449 	c.Next()        // zBlank
    450 	l, _ = c.Next() // zString
    451 	i, e1 := strconv.ParseUint(l.token, 10, 16)
    452 	if e1 != nil || l.err {
    453 		return &ParseError{"", "bad SRV Weight", l}
    454 	}
    455 	rr.Weight = uint16(i)
    456 
    457 	c.Next()        // zBlank
    458 	l, _ = c.Next() // zString
    459 	i, e2 := strconv.ParseUint(l.token, 10, 16)
    460 	if e2 != nil || l.err {
    461 		return &ParseError{"", "bad SRV Port", l}
    462 	}
    463 	rr.Port = uint16(i)
    464 
    465 	c.Next()        // zBlank
    466 	l, _ = c.Next() // zString
    467 	rr.Target = l.token
    468 
    469 	name, nameOk := toAbsoluteName(l.token, o)
    470 	if l.err || !nameOk {
    471 		return &ParseError{"", "bad SRV Target", l}
    472 	}
    473 	rr.Target = name
    474 	return slurpRemainder(c)
    475 }
    476 
    477 func (rr *NAPTR) parse(c *zlexer, o string) *ParseError {
    478 	l, _ := c.Next()
    479 	i, e := strconv.ParseUint(l.token, 10, 16)
    480 	if e != nil || l.err {
    481 		return &ParseError{"", "bad NAPTR Order", l}
    482 	}
    483 	rr.Order = uint16(i)
    484 
    485 	c.Next()        // zBlank
    486 	l, _ = c.Next() // zString
    487 	i, e1 := strconv.ParseUint(l.token, 10, 16)
    488 	if e1 != nil || l.err {
    489 		return &ParseError{"", "bad NAPTR Preference", l}
    490 	}
    491 	rr.Preference = uint16(i)
    492 
    493 	// Flags
    494 	c.Next()        // zBlank
    495 	l, _ = c.Next() // _QUOTE
    496 	if l.value != zQuote {
    497 		return &ParseError{"", "bad NAPTR Flags", l}
    498 	}
    499 	l, _ = c.Next() // Either String or Quote
    500 	if l.value == zString {
    501 		rr.Flags = l.token
    502 		l, _ = c.Next() // _QUOTE
    503 		if l.value != zQuote {
    504 			return &ParseError{"", "bad NAPTR Flags", l}
    505 		}
    506 	} else if l.value == zQuote {
    507 		rr.Flags = ""
    508 	} else {
    509 		return &ParseError{"", "bad NAPTR Flags", l}
    510 	}
    511 
    512 	// Service
    513 	c.Next()        // zBlank
    514 	l, _ = c.Next() // _QUOTE
    515 	if l.value != zQuote {
    516 		return &ParseError{"", "bad NAPTR Service", l}
    517 	}
    518 	l, _ = c.Next() // Either String or Quote
    519 	if l.value == zString {
    520 		rr.Service = l.token
    521 		l, _ = c.Next() // _QUOTE
    522 		if l.value != zQuote {
    523 			return &ParseError{"", "bad NAPTR Service", l}
    524 		}
    525 	} else if l.value == zQuote {
    526 		rr.Service = ""
    527 	} else {
    528 		return &ParseError{"", "bad NAPTR Service", l}
    529 	}
    530 
    531 	// Regexp
    532 	c.Next()        // zBlank
    533 	l, _ = c.Next() // _QUOTE
    534 	if l.value != zQuote {
    535 		return &ParseError{"", "bad NAPTR Regexp", l}
    536 	}
    537 	l, _ = c.Next() // Either String or Quote
    538 	if l.value == zString {
    539 		rr.Regexp = l.token
    540 		l, _ = c.Next() // _QUOTE
    541 		if l.value != zQuote {
    542 			return &ParseError{"", "bad NAPTR Regexp", l}
    543 		}
    544 	} else if l.value == zQuote {
    545 		rr.Regexp = ""
    546 	} else {
    547 		return &ParseError{"", "bad NAPTR Regexp", l}
    548 	}
    549 
    550 	// After quote no space??
    551 	c.Next()        // zBlank
    552 	l, _ = c.Next() // zString
    553 	rr.Replacement = l.token
    554 
    555 	name, nameOk := toAbsoluteName(l.token, o)
    556 	if l.err || !nameOk {
    557 		return &ParseError{"", "bad NAPTR Replacement", l}
    558 	}
    559 	rr.Replacement = name
    560 	return slurpRemainder(c)
    561 }
    562 
    563 func (rr *TALINK) parse(c *zlexer, o string) *ParseError {
    564 	l, _ := c.Next()
    565 	previousName, previousNameOk := toAbsoluteName(l.token, o)
    566 	if l.err || !previousNameOk {
    567 		return &ParseError{"", "bad TALINK PreviousName", l}
    568 	}
    569 	rr.PreviousName = previousName
    570 
    571 	c.Next() // zBlank
    572 	l, _ = c.Next()
    573 	rr.NextName = l.token
    574 
    575 	nextName, nextNameOk := toAbsoluteName(l.token, o)
    576 	if l.err || !nextNameOk {
    577 		return &ParseError{"", "bad TALINK NextName", l}
    578 	}
    579 	rr.NextName = nextName
    580 
    581 	return slurpRemainder(c)
    582 }
    583 
    584 func (rr *LOC) parse(c *zlexer, o string) *ParseError {
    585 	// Non zero defaults for LOC record, see RFC 1876, Section 3.
    586 	rr.Size = 0x12     // 1e2 cm (1m)
    587 	rr.HorizPre = 0x16 // 1e6 cm (10000m)
    588 	rr.VertPre = 0x13  // 1e3 cm (10m)
    589 	ok := false
    590 
    591 	// North
    592 	l, _ := c.Next()
    593 	i, e := strconv.ParseUint(l.token, 10, 32)
    594 	if e != nil || l.err || i > 90 {
    595 		return &ParseError{"", "bad LOC Latitude", l}
    596 	}
    597 	rr.Latitude = 1000 * 60 * 60 * uint32(i)
    598 
    599 	c.Next() // zBlank
    600 	// Either number, 'N' or 'S'
    601 	l, _ = c.Next()
    602 	if rr.Latitude, ok = locCheckNorth(l.token, rr.Latitude); ok {
    603 		goto East
    604 	}
    605 	if i, err := strconv.ParseUint(l.token, 10, 32); err != nil || l.err || i > 59 {
    606 		return &ParseError{"", "bad LOC Latitude minutes", l}
    607 	} else {
    608 		rr.Latitude += 1000 * 60 * uint32(i)
    609 	}
    610 
    611 	c.Next() // zBlank
    612 	l, _ = c.Next()
    613 	if i, err := strconv.ParseFloat(l.token, 64); err != nil || l.err || i < 0 || i >= 60 {
    614 		return &ParseError{"", "bad LOC Latitude seconds", l}
    615 	} else {
    616 		rr.Latitude += uint32(1000 * i)
    617 	}
    618 	c.Next() // zBlank
    619 	// Either number, 'N' or 'S'
    620 	l, _ = c.Next()
    621 	if rr.Latitude, ok = locCheckNorth(l.token, rr.Latitude); ok {
    622 		goto East
    623 	}
    624 	// If still alive, flag an error
    625 	return &ParseError{"", "bad LOC Latitude North/South", l}
    626 
    627 East:
    628 	// East
    629 	c.Next() // zBlank
    630 	l, _ = c.Next()
    631 	if i, err := strconv.ParseUint(l.token, 10, 32); err != nil || l.err || i > 180 {
    632 		return &ParseError{"", "bad LOC Longitude", l}
    633 	} else {
    634 		rr.Longitude = 1000 * 60 * 60 * uint32(i)
    635 	}
    636 	c.Next() // zBlank
    637 	// Either number, 'E' or 'W'
    638 	l, _ = c.Next()
    639 	if rr.Longitude, ok = locCheckEast(l.token, rr.Longitude); ok {
    640 		goto Altitude
    641 	}
    642 	if i, err := strconv.ParseUint(l.token, 10, 32); err != nil || l.err || i > 59 {
    643 		return &ParseError{"", "bad LOC Longitude minutes", l}
    644 	} else {
    645 		rr.Longitude += 1000 * 60 * uint32(i)
    646 	}
    647 	c.Next() // zBlank
    648 	l, _ = c.Next()
    649 	if i, err := strconv.ParseFloat(l.token, 64); err != nil || l.err || i < 0 || i >= 60 {
    650 		return &ParseError{"", "bad LOC Longitude seconds", l}
    651 	} else {
    652 		rr.Longitude += uint32(1000 * i)
    653 	}
    654 	c.Next() // zBlank
    655 	// Either number, 'E' or 'W'
    656 	l, _ = c.Next()
    657 	if rr.Longitude, ok = locCheckEast(l.token, rr.Longitude); ok {
    658 		goto Altitude
    659 	}
    660 	// If still alive, flag an error
    661 	return &ParseError{"", "bad LOC Longitude East/West", l}
    662 
    663 Altitude:
    664 	c.Next() // zBlank
    665 	l, _ = c.Next()
    666 	if l.token == "" || l.err {
    667 		return &ParseError{"", "bad LOC Altitude", l}
    668 	}
    669 	if l.token[len(l.token)-1] == 'M' || l.token[len(l.token)-1] == 'm' {
    670 		l.token = l.token[0 : len(l.token)-1]
    671 	}
    672 	if i, err := strconv.ParseFloat(l.token, 64); err != nil {
    673 		return &ParseError{"", "bad LOC Altitude", l}
    674 	} else {
    675 		rr.Altitude = uint32(i*100.0 + 10000000.0 + 0.5)
    676 	}
    677 
    678 	// And now optionally the other values
    679 	l, _ = c.Next()
    680 	count := 0
    681 	for l.value != zNewline && l.value != zEOF {
    682 		switch l.value {
    683 		case zString:
    684 			switch count {
    685 			case 0: // Size
    686 				exp, m, ok := stringToCm(l.token)
    687 				if !ok {
    688 					return &ParseError{"", "bad LOC Size", l}
    689 				}
    690 				rr.Size = exp&0x0f | m<<4&0xf0
    691 			case 1: // HorizPre
    692 				exp, m, ok := stringToCm(l.token)
    693 				if !ok {
    694 					return &ParseError{"", "bad LOC HorizPre", l}
    695 				}
    696 				rr.HorizPre = exp&0x0f | m<<4&0xf0
    697 			case 2: // VertPre
    698 				exp, m, ok := stringToCm(l.token)
    699 				if !ok {
    700 					return &ParseError{"", "bad LOC VertPre", l}
    701 				}
    702 				rr.VertPre = exp&0x0f | m<<4&0xf0
    703 			}
    704 			count++
    705 		case zBlank:
    706 			// Ok
    707 		default:
    708 			return &ParseError{"", "bad LOC Size, HorizPre or VertPre", l}
    709 		}
    710 		l, _ = c.Next()
    711 	}
    712 	return nil
    713 }
    714 
    715 func (rr *HIP) parse(c *zlexer, o string) *ParseError {
    716 	// HitLength is not represented
    717 	l, _ := c.Next()
    718 	i, e := strconv.ParseUint(l.token, 10, 8)
    719 	if e != nil || l.err {
    720 		return &ParseError{"", "bad HIP PublicKeyAlgorithm", l}
    721 	}
    722 	rr.PublicKeyAlgorithm = uint8(i)
    723 
    724 	c.Next()        // zBlank
    725 	l, _ = c.Next() // zString
    726 	if l.token == "" || l.err {
    727 		return &ParseError{"", "bad HIP Hit", l}
    728 	}
    729 	rr.Hit = l.token // This can not contain spaces, see RFC 5205 Section 6.
    730 	rr.HitLength = uint8(len(rr.Hit)) / 2
    731 
    732 	c.Next()        // zBlank
    733 	l, _ = c.Next() // zString
    734 	if l.token == "" || l.err {
    735 		return &ParseError{"", "bad HIP PublicKey", l}
    736 	}
    737 	rr.PublicKey = l.token // This cannot contain spaces
    738 	decodedPK, decodedPKerr := base64.StdEncoding.DecodeString(rr.PublicKey)
    739 	if decodedPKerr != nil {
    740 		return &ParseError{"", "bad HIP PublicKey", l}
    741 	}
    742 	rr.PublicKeyLength = uint16(len(decodedPK))
    743 
    744 	// RendezvousServers (if any)
    745 	l, _ = c.Next()
    746 	var xs []string
    747 	for l.value != zNewline && l.value != zEOF {
    748 		switch l.value {
    749 		case zString:
    750 			name, nameOk := toAbsoluteName(l.token, o)
    751 			if l.err || !nameOk {
    752 				return &ParseError{"", "bad HIP RendezvousServers", l}
    753 			}
    754 			xs = append(xs, name)
    755 		case zBlank:
    756 			// Ok
    757 		default:
    758 			return &ParseError{"", "bad HIP RendezvousServers", l}
    759 		}
    760 		l, _ = c.Next()
    761 	}
    762 
    763 	rr.RendezvousServers = xs
    764 	return nil
    765 }
    766 
    767 func (rr *CERT) parse(c *zlexer, o string) *ParseError {
    768 	l, _ := c.Next()
    769 	if v, ok := StringToCertType[l.token]; ok {
    770 		rr.Type = v
    771 	} else if i, err := strconv.ParseUint(l.token, 10, 16); err != nil {
    772 		return &ParseError{"", "bad CERT Type", l}
    773 	} else {
    774 		rr.Type = uint16(i)
    775 	}
    776 	c.Next()        // zBlank
    777 	l, _ = c.Next() // zString
    778 	i, e := strconv.ParseUint(l.token, 10, 16)
    779 	if e != nil || l.err {
    780 		return &ParseError{"", "bad CERT KeyTag", l}
    781 	}
    782 	rr.KeyTag = uint16(i)
    783 	c.Next()        // zBlank
    784 	l, _ = c.Next() // zString
    785 	if v, ok := StringToAlgorithm[l.token]; ok {
    786 		rr.Algorithm = v
    787 	} else if i, err := strconv.ParseUint(l.token, 10, 8); err != nil {
    788 		return &ParseError{"", "bad CERT Algorithm", l}
    789 	} else {
    790 		rr.Algorithm = uint8(i)
    791 	}
    792 	s, e1 := endingToString(c, "bad CERT Certificate")
    793 	if e1 != nil {
    794 		return e1
    795 	}
    796 	rr.Certificate = s
    797 	return nil
    798 }
    799 
    800 func (rr *OPENPGPKEY) parse(c *zlexer, o string) *ParseError {
    801 	s, e := endingToString(c, "bad OPENPGPKEY PublicKey")
    802 	if e != nil {
    803 		return e
    804 	}
    805 	rr.PublicKey = s
    806 	return nil
    807 }
    808 
    809 func (rr *CSYNC) parse(c *zlexer, o string) *ParseError {
    810 	l, _ := c.Next()
    811 	j, e := strconv.ParseUint(l.token, 10, 32)
    812 	if e != nil {
    813 		// Serial must be a number
    814 		return &ParseError{"", "bad CSYNC serial", l}
    815 	}
    816 	rr.Serial = uint32(j)
    817 
    818 	c.Next() // zBlank
    819 
    820 	l, _ = c.Next()
    821 	j, e1 := strconv.ParseUint(l.token, 10, 16)
    822 	if e1 != nil {
    823 		// Serial must be a number
    824 		return &ParseError{"", "bad CSYNC flags", l}
    825 	}
    826 	rr.Flags = uint16(j)
    827 
    828 	rr.TypeBitMap = make([]uint16, 0)
    829 	var (
    830 		k  uint16
    831 		ok bool
    832 	)
    833 	l, _ = c.Next()
    834 	for l.value != zNewline && l.value != zEOF {
    835 		switch l.value {
    836 		case zBlank:
    837 			// Ok
    838 		case zString:
    839 			tokenUpper := strings.ToUpper(l.token)
    840 			if k, ok = StringToType[tokenUpper]; !ok {
    841 				if k, ok = typeToInt(l.token); !ok {
    842 					return &ParseError{"", "bad CSYNC TypeBitMap", l}
    843 				}
    844 			}
    845 			rr.TypeBitMap = append(rr.TypeBitMap, k)
    846 		default:
    847 			return &ParseError{"", "bad CSYNC TypeBitMap", l}
    848 		}
    849 		l, _ = c.Next()
    850 	}
    851 	return nil
    852 }
    853 
    854 func (rr *ZONEMD) parse(c *zlexer, o string) *ParseError {
    855 	l, _ := c.Next()
    856 	i, e := strconv.ParseUint(l.token, 10, 32)
    857 	if e != nil || l.err {
    858 		return &ParseError{"", "bad ZONEMD Serial", l}
    859 	}
    860 	rr.Serial = uint32(i)
    861 
    862 	c.Next() // zBlank
    863 	l, _ = c.Next()
    864 	i, e1 := strconv.ParseUint(l.token, 10, 8)
    865 	if e1 != nil || l.err {
    866 		return &ParseError{"", "bad ZONEMD Scheme", l}
    867 	}
    868 	rr.Scheme = uint8(i)
    869 
    870 	c.Next() // zBlank
    871 	l, _ = c.Next()
    872 	i, err := strconv.ParseUint(l.token, 10, 8)
    873 	if err != nil || l.err {
    874 		return &ParseError{"", "bad ZONEMD Hash Algorithm", l}
    875 	}
    876 	rr.Hash = uint8(i)
    877 
    878 	s, e2 := endingToString(c, "bad ZONEMD Digest")
    879 	if e2 != nil {
    880 		return e2
    881 	}
    882 	rr.Digest = s
    883 	return nil
    884 }
    885 
    886 func (rr *SIG) parse(c *zlexer, o string) *ParseError { return rr.RRSIG.parse(c, o) }
    887 
    888 func (rr *RRSIG) parse(c *zlexer, o string) *ParseError {
    889 	l, _ := c.Next()
    890 	tokenUpper := strings.ToUpper(l.token)
    891 	if t, ok := StringToType[tokenUpper]; !ok {
    892 		if strings.HasPrefix(tokenUpper, "TYPE") {
    893 			t, ok = typeToInt(l.token)
    894 			if !ok {
    895 				return &ParseError{"", "bad RRSIG Typecovered", l}
    896 			}
    897 			rr.TypeCovered = t
    898 		} else {
    899 			return &ParseError{"", "bad RRSIG Typecovered", l}
    900 		}
    901 	} else {
    902 		rr.TypeCovered = t
    903 	}
    904 
    905 	c.Next() // zBlank
    906 	l, _ = c.Next()
    907 	if l.err {
    908 		return &ParseError{"", "bad RRSIG Algorithm", l}
    909 	}
    910 	i, e := strconv.ParseUint(l.token, 10, 8)
    911 	rr.Algorithm = uint8(i) // if 0 we'll check the mnemonic in the if
    912 	if e != nil {
    913 		v, ok := StringToAlgorithm[l.token]
    914 		if !ok {
    915 			return &ParseError{"", "bad RRSIG Algorithm", l}
    916 		}
    917 		rr.Algorithm = v
    918 	}
    919 
    920 	c.Next() // zBlank
    921 	l, _ = c.Next()
    922 	i, e1 := strconv.ParseUint(l.token, 10, 8)
    923 	if e1 != nil || l.err {
    924 		return &ParseError{"", "bad RRSIG Labels", l}
    925 	}
    926 	rr.Labels = uint8(i)
    927 
    928 	c.Next() // zBlank
    929 	l, _ = c.Next()
    930 	i, e2 := strconv.ParseUint(l.token, 10, 32)
    931 	if e2 != nil || l.err {
    932 		return &ParseError{"", "bad RRSIG OrigTtl", l}
    933 	}
    934 	rr.OrigTtl = uint32(i)
    935 
    936 	c.Next() // zBlank
    937 	l, _ = c.Next()
    938 	if i, err := StringToTime(l.token); err != nil {
    939 		// Try to see if all numeric and use it as epoch
    940 		if i, err := strconv.ParseUint(l.token, 10, 32); err == nil {
    941 			rr.Expiration = uint32(i)
    942 		} else {
    943 			return &ParseError{"", "bad RRSIG Expiration", l}
    944 		}
    945 	} else {
    946 		rr.Expiration = i
    947 	}
    948 
    949 	c.Next() // zBlank
    950 	l, _ = c.Next()
    951 	if i, err := StringToTime(l.token); err != nil {
    952 		if i, err := strconv.ParseUint(l.token, 10, 32); err == nil {
    953 			rr.Inception = uint32(i)
    954 		} else {
    955 			return &ParseError{"", "bad RRSIG Inception", l}
    956 		}
    957 	} else {
    958 		rr.Inception = i
    959 	}
    960 
    961 	c.Next() // zBlank
    962 	l, _ = c.Next()
    963 	i, e3 := strconv.ParseUint(l.token, 10, 16)
    964 	if e3 != nil || l.err {
    965 		return &ParseError{"", "bad RRSIG KeyTag", l}
    966 	}
    967 	rr.KeyTag = uint16(i)
    968 
    969 	c.Next() // zBlank
    970 	l, _ = c.Next()
    971 	rr.SignerName = l.token
    972 	name, nameOk := toAbsoluteName(l.token, o)
    973 	if l.err || !nameOk {
    974 		return &ParseError{"", "bad RRSIG SignerName", l}
    975 	}
    976 	rr.SignerName = name
    977 
    978 	s, e4 := endingToString(c, "bad RRSIG Signature")
    979 	if e4 != nil {
    980 		return e4
    981 	}
    982 	rr.Signature = s
    983 
    984 	return nil
    985 }
    986 
    987 func (rr *NSEC) parse(c *zlexer, o string) *ParseError {
    988 	l, _ := c.Next()
    989 	name, nameOk := toAbsoluteName(l.token, o)
    990 	if l.err || !nameOk {
    991 		return &ParseError{"", "bad NSEC NextDomain", l}
    992 	}
    993 	rr.NextDomain = name
    994 
    995 	rr.TypeBitMap = make([]uint16, 0)
    996 	var (
    997 		k  uint16
    998 		ok bool
    999 	)
   1000 	l, _ = c.Next()
   1001 	for l.value != zNewline && l.value != zEOF {
   1002 		switch l.value {
   1003 		case zBlank:
   1004 			// Ok
   1005 		case zString:
   1006 			tokenUpper := strings.ToUpper(l.token)
   1007 			if k, ok = StringToType[tokenUpper]; !ok {
   1008 				if k, ok = typeToInt(l.token); !ok {
   1009 					return &ParseError{"", "bad NSEC TypeBitMap", l}
   1010 				}
   1011 			}
   1012 			rr.TypeBitMap = append(rr.TypeBitMap, k)
   1013 		default:
   1014 			return &ParseError{"", "bad NSEC TypeBitMap", l}
   1015 		}
   1016 		l, _ = c.Next()
   1017 	}
   1018 	return nil
   1019 }
   1020 
   1021 func (rr *NSEC3) parse(c *zlexer, o string) *ParseError {
   1022 	l, _ := c.Next()
   1023 	i, e := strconv.ParseUint(l.token, 10, 8)
   1024 	if e != nil || l.err {
   1025 		return &ParseError{"", "bad NSEC3 Hash", l}
   1026 	}
   1027 	rr.Hash = uint8(i)
   1028 	c.Next() // zBlank
   1029 	l, _ = c.Next()
   1030 	i, e1 := strconv.ParseUint(l.token, 10, 8)
   1031 	if e1 != nil || l.err {
   1032 		return &ParseError{"", "bad NSEC3 Flags", l}
   1033 	}
   1034 	rr.Flags = uint8(i)
   1035 	c.Next() // zBlank
   1036 	l, _ = c.Next()
   1037 	i, e2 := strconv.ParseUint(l.token, 10, 16)
   1038 	if e2 != nil || l.err {
   1039 		return &ParseError{"", "bad NSEC3 Iterations", l}
   1040 	}
   1041 	rr.Iterations = uint16(i)
   1042 	c.Next()
   1043 	l, _ = c.Next()
   1044 	if l.token == "" || l.err {
   1045 		return &ParseError{"", "bad NSEC3 Salt", l}
   1046 	}
   1047 	if l.token != "-" {
   1048 		rr.SaltLength = uint8(len(l.token)) / 2
   1049 		rr.Salt = l.token
   1050 	}
   1051 
   1052 	c.Next()
   1053 	l, _ = c.Next()
   1054 	if l.token == "" || l.err {
   1055 		return &ParseError{"", "bad NSEC3 NextDomain", l}
   1056 	}
   1057 	rr.HashLength = 20 // Fix for NSEC3 (sha1 160 bits)
   1058 	rr.NextDomain = l.token
   1059 
   1060 	rr.TypeBitMap = make([]uint16, 0)
   1061 	var (
   1062 		k  uint16
   1063 		ok bool
   1064 	)
   1065 	l, _ = c.Next()
   1066 	for l.value != zNewline && l.value != zEOF {
   1067 		switch l.value {
   1068 		case zBlank:
   1069 			// Ok
   1070 		case zString:
   1071 			tokenUpper := strings.ToUpper(l.token)
   1072 			if k, ok = StringToType[tokenUpper]; !ok {
   1073 				if k, ok = typeToInt(l.token); !ok {
   1074 					return &ParseError{"", "bad NSEC3 TypeBitMap", l}
   1075 				}
   1076 			}
   1077 			rr.TypeBitMap = append(rr.TypeBitMap, k)
   1078 		default:
   1079 			return &ParseError{"", "bad NSEC3 TypeBitMap", l}
   1080 		}
   1081 		l, _ = c.Next()
   1082 	}
   1083 	return nil
   1084 }
   1085 
   1086 func (rr *NSEC3PARAM) parse(c *zlexer, o string) *ParseError {
   1087 	l, _ := c.Next()
   1088 	i, e := strconv.ParseUint(l.token, 10, 8)
   1089 	if e != nil || l.err {
   1090 		return &ParseError{"", "bad NSEC3PARAM Hash", l}
   1091 	}
   1092 	rr.Hash = uint8(i)
   1093 	c.Next() // zBlank
   1094 	l, _ = c.Next()
   1095 	i, e1 := strconv.ParseUint(l.token, 10, 8)
   1096 	if e1 != nil || l.err {
   1097 		return &ParseError{"", "bad NSEC3PARAM Flags", l}
   1098 	}
   1099 	rr.Flags = uint8(i)
   1100 	c.Next() // zBlank
   1101 	l, _ = c.Next()
   1102 	i, e2 := strconv.ParseUint(l.token, 10, 16)
   1103 	if e2 != nil || l.err {
   1104 		return &ParseError{"", "bad NSEC3PARAM Iterations", l}
   1105 	}
   1106 	rr.Iterations = uint16(i)
   1107 	c.Next()
   1108 	l, _ = c.Next()
   1109 	if l.token != "-" {
   1110 		rr.SaltLength = uint8(len(l.token) / 2)
   1111 		rr.Salt = l.token
   1112 	}
   1113 	return slurpRemainder(c)
   1114 }
   1115 
   1116 func (rr *EUI48) parse(c *zlexer, o string) *ParseError {
   1117 	l, _ := c.Next()
   1118 	if len(l.token) != 17 || l.err {
   1119 		return &ParseError{"", "bad EUI48 Address", l}
   1120 	}
   1121 	addr := make([]byte, 12)
   1122 	dash := 0
   1123 	for i := 0; i < 10; i += 2 {
   1124 		addr[i] = l.token[i+dash]
   1125 		addr[i+1] = l.token[i+1+dash]
   1126 		dash++
   1127 		if l.token[i+1+dash] != '-' {
   1128 			return &ParseError{"", "bad EUI48 Address", l}
   1129 		}
   1130 	}
   1131 	addr[10] = l.token[15]
   1132 	addr[11] = l.token[16]
   1133 
   1134 	i, e := strconv.ParseUint(string(addr), 16, 48)
   1135 	if e != nil {
   1136 		return &ParseError{"", "bad EUI48 Address", l}
   1137 	}
   1138 	rr.Address = i
   1139 	return slurpRemainder(c)
   1140 }
   1141 
   1142 func (rr *EUI64) parse(c *zlexer, o string) *ParseError {
   1143 	l, _ := c.Next()
   1144 	if len(l.token) != 23 || l.err {
   1145 		return &ParseError{"", "bad EUI64 Address", l}
   1146 	}
   1147 	addr := make([]byte, 16)
   1148 	dash := 0
   1149 	for i := 0; i < 14; i += 2 {
   1150 		addr[i] = l.token[i+dash]
   1151 		addr[i+1] = l.token[i+1+dash]
   1152 		dash++
   1153 		if l.token[i+1+dash] != '-' {
   1154 			return &ParseError{"", "bad EUI64 Address", l}
   1155 		}
   1156 	}
   1157 	addr[14] = l.token[21]
   1158 	addr[15] = l.token[22]
   1159 
   1160 	i, e := strconv.ParseUint(string(addr), 16, 64)
   1161 	if e != nil {
   1162 		return &ParseError{"", "bad EUI68 Address", l}
   1163 	}
   1164 	rr.Address = i
   1165 	return slurpRemainder(c)
   1166 }
   1167 
   1168 func (rr *SSHFP) parse(c *zlexer, o string) *ParseError {
   1169 	l, _ := c.Next()
   1170 	i, e := strconv.ParseUint(l.token, 10, 8)
   1171 	if e != nil || l.err {
   1172 		return &ParseError{"", "bad SSHFP Algorithm", l}
   1173 	}
   1174 	rr.Algorithm = uint8(i)
   1175 	c.Next() // zBlank
   1176 	l, _ = c.Next()
   1177 	i, e1 := strconv.ParseUint(l.token, 10, 8)
   1178 	if e1 != nil || l.err {
   1179 		return &ParseError{"", "bad SSHFP Type", l}
   1180 	}
   1181 	rr.Type = uint8(i)
   1182 	c.Next() // zBlank
   1183 	s, e2 := endingToString(c, "bad SSHFP Fingerprint")
   1184 	if e2 != nil {
   1185 		return e2
   1186 	}
   1187 	rr.FingerPrint = s
   1188 	return nil
   1189 }
   1190 
   1191 func (rr *DNSKEY) parseDNSKEY(c *zlexer, o, typ string) *ParseError {
   1192 	l, _ := c.Next()
   1193 	i, e := strconv.ParseUint(l.token, 10, 16)
   1194 	if e != nil || l.err {
   1195 		return &ParseError{"", "bad " + typ + " Flags", l}
   1196 	}
   1197 	rr.Flags = uint16(i)
   1198 	c.Next()        // zBlank
   1199 	l, _ = c.Next() // zString
   1200 	i, e1 := strconv.ParseUint(l.token, 10, 8)
   1201 	if e1 != nil || l.err {
   1202 		return &ParseError{"", "bad " + typ + " Protocol", l}
   1203 	}
   1204 	rr.Protocol = uint8(i)
   1205 	c.Next()        // zBlank
   1206 	l, _ = c.Next() // zString
   1207 	i, e2 := strconv.ParseUint(l.token, 10, 8)
   1208 	if e2 != nil || l.err {
   1209 		return &ParseError{"", "bad " + typ + " Algorithm", l}
   1210 	}
   1211 	rr.Algorithm = uint8(i)
   1212 	s, e3 := endingToString(c, "bad "+typ+" PublicKey")
   1213 	if e3 != nil {
   1214 		return e3
   1215 	}
   1216 	rr.PublicKey = s
   1217 	return nil
   1218 }
   1219 
   1220 func (rr *DNSKEY) parse(c *zlexer, o string) *ParseError  { return rr.parseDNSKEY(c, o, "DNSKEY") }
   1221 func (rr *KEY) parse(c *zlexer, o string) *ParseError     { return rr.parseDNSKEY(c, o, "KEY") }
   1222 func (rr *CDNSKEY) parse(c *zlexer, o string) *ParseError { return rr.parseDNSKEY(c, o, "CDNSKEY") }
   1223 func (rr *DS) parse(c *zlexer, o string) *ParseError      { return rr.parseDS(c, o, "DS") }
   1224 func (rr *DLV) parse(c *zlexer, o string) *ParseError     { return rr.parseDS(c, o, "DLV") }
   1225 func (rr *CDS) parse(c *zlexer, o string) *ParseError     { return rr.parseDS(c, o, "CDS") }
   1226 
   1227 func (rr *IPSECKEY) parse(c *zlexer, o string) *ParseError {
   1228 	l, _ := c.Next()
   1229 	num, err := strconv.ParseUint(l.token, 10, 8)
   1230 	if err != nil || l.err {
   1231 		return &ParseError{"", "bad IPSECKEY value", l}
   1232 	}
   1233 	rr.Precedence = uint8(num)
   1234 	c.Next() // zBlank
   1235 
   1236 	l, _ = c.Next()
   1237 	num, err = strconv.ParseUint(l.token, 10, 8)
   1238 	if err != nil || l.err {
   1239 		return &ParseError{"", "bad IPSECKEY value", l}
   1240 	}
   1241 	rr.GatewayType = uint8(num)
   1242 	c.Next() // zBlank
   1243 
   1244 	l, _ = c.Next()
   1245 	num, err = strconv.ParseUint(l.token, 10, 8)
   1246 	if err != nil || l.err {
   1247 		return &ParseError{"", "bad IPSECKEY value", l}
   1248 	}
   1249 	rr.Algorithm = uint8(num)
   1250 	c.Next() // zBlank
   1251 
   1252 	l, _ = c.Next()
   1253 	if l.err {
   1254 		return &ParseError{"", "bad IPSECKEY gateway", l}
   1255 	}
   1256 
   1257 	rr.GatewayAddr, rr.GatewayHost, err = parseAddrHostUnion(l.token, o, rr.GatewayType)
   1258 	if err != nil {
   1259 		return &ParseError{"", "IPSECKEY " + err.Error(), l}
   1260 	}
   1261 
   1262 	c.Next() // zBlank
   1263 
   1264 	s, pErr := endingToString(c, "bad IPSECKEY PublicKey")
   1265 	if pErr != nil {
   1266 		return pErr
   1267 	}
   1268 	rr.PublicKey = s
   1269 	return slurpRemainder(c)
   1270 }
   1271 
   1272 func (rr *AMTRELAY) parse(c *zlexer, o string) *ParseError {
   1273 	l, _ := c.Next()
   1274 	num, err := strconv.ParseUint(l.token, 10, 8)
   1275 	if err != nil || l.err {
   1276 		return &ParseError{"", "bad AMTRELAY value", l}
   1277 	}
   1278 	rr.Precedence = uint8(num)
   1279 	c.Next() // zBlank
   1280 
   1281 	l, _ = c.Next()
   1282 	if l.err || !(l.token == "0" || l.token == "1") {
   1283 		return &ParseError{"", "bad discovery value", l}
   1284 	}
   1285 	if l.token == "1" {
   1286 		rr.GatewayType = 0x80
   1287 	}
   1288 
   1289 	c.Next() // zBlank
   1290 
   1291 	l, _ = c.Next()
   1292 	num, err = strconv.ParseUint(l.token, 10, 8)
   1293 	if err != nil || l.err {
   1294 		return &ParseError{"", "bad AMTRELAY value", l}
   1295 	}
   1296 	rr.GatewayType |= uint8(num)
   1297 	c.Next() // zBlank
   1298 
   1299 	l, _ = c.Next()
   1300 	if l.err {
   1301 		return &ParseError{"", "bad AMTRELAY gateway", l}
   1302 	}
   1303 
   1304 	rr.GatewayAddr, rr.GatewayHost, err = parseAddrHostUnion(l.token, o, rr.GatewayType&0x7f)
   1305 	if err != nil {
   1306 		return &ParseError{"", "AMTRELAY " + err.Error(), l}
   1307 	}
   1308 
   1309 	return slurpRemainder(c)
   1310 }
   1311 
   1312 // same constants and parsing between IPSECKEY and AMTRELAY
   1313 func parseAddrHostUnion(token, o string, gatewayType uint8) (addr net.IP, host string, err error) {
   1314 	switch gatewayType {
   1315 	case IPSECGatewayNone:
   1316 		if token != "." {
   1317 			return addr, host, errors.New("gateway type none with gateway set")
   1318 		}
   1319 	case IPSECGatewayIPv4, IPSECGatewayIPv6:
   1320 		addr = net.ParseIP(token)
   1321 		if addr == nil {
   1322 			return addr, host, errors.New("gateway IP invalid")
   1323 		}
   1324 		if (addr.To4() == nil) == (gatewayType == IPSECGatewayIPv4) {
   1325 			return addr, host, errors.New("gateway IP family mismatch")
   1326 		}
   1327 	case IPSECGatewayHost:
   1328 		var ok bool
   1329 		host, ok = toAbsoluteName(token, o)
   1330 		if !ok {
   1331 			return addr, host, errors.New("invalid gateway host")
   1332 		}
   1333 	}
   1334 
   1335 	return addr, host, nil
   1336 }
   1337 
   1338 func (rr *RKEY) parse(c *zlexer, o string) *ParseError {
   1339 	l, _ := c.Next()
   1340 	i, e := strconv.ParseUint(l.token, 10, 16)
   1341 	if e != nil || l.err {
   1342 		return &ParseError{"", "bad RKEY Flags", l}
   1343 	}
   1344 	rr.Flags = uint16(i)
   1345 	c.Next()        // zBlank
   1346 	l, _ = c.Next() // zString
   1347 	i, e1 := strconv.ParseUint(l.token, 10, 8)
   1348 	if e1 != nil || l.err {
   1349 		return &ParseError{"", "bad RKEY Protocol", l}
   1350 	}
   1351 	rr.Protocol = uint8(i)
   1352 	c.Next()        // zBlank
   1353 	l, _ = c.Next() // zString
   1354 	i, e2 := strconv.ParseUint(l.token, 10, 8)
   1355 	if e2 != nil || l.err {
   1356 		return &ParseError{"", "bad RKEY Algorithm", l}
   1357 	}
   1358 	rr.Algorithm = uint8(i)
   1359 	s, e3 := endingToString(c, "bad RKEY PublicKey")
   1360 	if e3 != nil {
   1361 		return e3
   1362 	}
   1363 	rr.PublicKey = s
   1364 	return nil
   1365 }
   1366 
   1367 func (rr *EID) parse(c *zlexer, o string) *ParseError {
   1368 	s, e := endingToString(c, "bad EID Endpoint")
   1369 	if e != nil {
   1370 		return e
   1371 	}
   1372 	rr.Endpoint = s
   1373 	return nil
   1374 }
   1375 
   1376 func (rr *NIMLOC) parse(c *zlexer, o string) *ParseError {
   1377 	s, e := endingToString(c, "bad NIMLOC Locator")
   1378 	if e != nil {
   1379 		return e
   1380 	}
   1381 	rr.Locator = s
   1382 	return nil
   1383 }
   1384 
   1385 func (rr *GPOS) parse(c *zlexer, o string) *ParseError {
   1386 	l, _ := c.Next()
   1387 	_, e := strconv.ParseFloat(l.token, 64)
   1388 	if e != nil || l.err {
   1389 		return &ParseError{"", "bad GPOS Longitude", l}
   1390 	}
   1391 	rr.Longitude = l.token
   1392 	c.Next() // zBlank
   1393 	l, _ = c.Next()
   1394 	_, e1 := strconv.ParseFloat(l.token, 64)
   1395 	if e1 != nil || l.err {
   1396 		return &ParseError{"", "bad GPOS Latitude", l}
   1397 	}
   1398 	rr.Latitude = l.token
   1399 	c.Next() // zBlank
   1400 	l, _ = c.Next()
   1401 	_, e2 := strconv.ParseFloat(l.token, 64)
   1402 	if e2 != nil || l.err {
   1403 		return &ParseError{"", "bad GPOS Altitude", l}
   1404 	}
   1405 	rr.Altitude = l.token
   1406 	return slurpRemainder(c)
   1407 }
   1408 
   1409 func (rr *DS) parseDS(c *zlexer, o, typ string) *ParseError {
   1410 	l, _ := c.Next()
   1411 	i, e := strconv.ParseUint(l.token, 10, 16)
   1412 	if e != nil || l.err {
   1413 		return &ParseError{"", "bad " + typ + " KeyTag", l}
   1414 	}
   1415 	rr.KeyTag = uint16(i)
   1416 	c.Next() // zBlank
   1417 	l, _ = c.Next()
   1418 	if i, err := strconv.ParseUint(l.token, 10, 8); err != nil {
   1419 		tokenUpper := strings.ToUpper(l.token)
   1420 		i, ok := StringToAlgorithm[tokenUpper]
   1421 		if !ok || l.err {
   1422 			return &ParseError{"", "bad " + typ + " Algorithm", l}
   1423 		}
   1424 		rr.Algorithm = i
   1425 	} else {
   1426 		rr.Algorithm = uint8(i)
   1427 	}
   1428 	c.Next() // zBlank
   1429 	l, _ = c.Next()
   1430 	i, e1 := strconv.ParseUint(l.token, 10, 8)
   1431 	if e1 != nil || l.err {
   1432 		return &ParseError{"", "bad " + typ + " DigestType", l}
   1433 	}
   1434 	rr.DigestType = uint8(i)
   1435 	s, e2 := endingToString(c, "bad "+typ+" Digest")
   1436 	if e2 != nil {
   1437 		return e2
   1438 	}
   1439 	rr.Digest = s
   1440 	return nil
   1441 }
   1442 
   1443 func (rr *TA) parse(c *zlexer, o string) *ParseError {
   1444 	l, _ := c.Next()
   1445 	i, e := strconv.ParseUint(l.token, 10, 16)
   1446 	if e != nil || l.err {
   1447 		return &ParseError{"", "bad TA KeyTag", l}
   1448 	}
   1449 	rr.KeyTag = uint16(i)
   1450 	c.Next() // zBlank
   1451 	l, _ = c.Next()
   1452 	if i, err := strconv.ParseUint(l.token, 10, 8); err != nil {
   1453 		tokenUpper := strings.ToUpper(l.token)
   1454 		i, ok := StringToAlgorithm[tokenUpper]
   1455 		if !ok || l.err {
   1456 			return &ParseError{"", "bad TA Algorithm", l}
   1457 		}
   1458 		rr.Algorithm = i
   1459 	} else {
   1460 		rr.Algorithm = uint8(i)
   1461 	}
   1462 	c.Next() // zBlank
   1463 	l, _ = c.Next()
   1464 	i, e1 := strconv.ParseUint(l.token, 10, 8)
   1465 	if e1 != nil || l.err {
   1466 		return &ParseError{"", "bad TA DigestType", l}
   1467 	}
   1468 	rr.DigestType = uint8(i)
   1469 	s, e2 := endingToString(c, "bad TA Digest")
   1470 	if e2 != nil {
   1471 		return e2
   1472 	}
   1473 	rr.Digest = s
   1474 	return nil
   1475 }
   1476 
   1477 func (rr *TLSA) parse(c *zlexer, o string) *ParseError {
   1478 	l, _ := c.Next()
   1479 	i, e := strconv.ParseUint(l.token, 10, 8)
   1480 	if e != nil || l.err {
   1481 		return &ParseError{"", "bad TLSA Usage", l}
   1482 	}
   1483 	rr.Usage = uint8(i)
   1484 	c.Next() // zBlank
   1485 	l, _ = c.Next()
   1486 	i, e1 := strconv.ParseUint(l.token, 10, 8)
   1487 	if e1 != nil || l.err {
   1488 		return &ParseError{"", "bad TLSA Selector", l}
   1489 	}
   1490 	rr.Selector = uint8(i)
   1491 	c.Next() // zBlank
   1492 	l, _ = c.Next()
   1493 	i, e2 := strconv.ParseUint(l.token, 10, 8)
   1494 	if e2 != nil || l.err {
   1495 		return &ParseError{"", "bad TLSA MatchingType", l}
   1496 	}
   1497 	rr.MatchingType = uint8(i)
   1498 	// So this needs be e2 (i.e. different than e), because...??t
   1499 	s, e3 := endingToString(c, "bad TLSA Certificate")
   1500 	if e3 != nil {
   1501 		return e3
   1502 	}
   1503 	rr.Certificate = s
   1504 	return nil
   1505 }
   1506 
   1507 func (rr *SMIMEA) parse(c *zlexer, o string) *ParseError {
   1508 	l, _ := c.Next()
   1509 	i, e := strconv.ParseUint(l.token, 10, 8)
   1510 	if e != nil || l.err {
   1511 		return &ParseError{"", "bad SMIMEA Usage", l}
   1512 	}
   1513 	rr.Usage = uint8(i)
   1514 	c.Next() // zBlank
   1515 	l, _ = c.Next()
   1516 	i, e1 := strconv.ParseUint(l.token, 10, 8)
   1517 	if e1 != nil || l.err {
   1518 		return &ParseError{"", "bad SMIMEA Selector", l}
   1519 	}
   1520 	rr.Selector = uint8(i)
   1521 	c.Next() // zBlank
   1522 	l, _ = c.Next()
   1523 	i, e2 := strconv.ParseUint(l.token, 10, 8)
   1524 	if e2 != nil || l.err {
   1525 		return &ParseError{"", "bad SMIMEA MatchingType", l}
   1526 	}
   1527 	rr.MatchingType = uint8(i)
   1528 	// So this needs be e2 (i.e. different than e), because...??t
   1529 	s, e3 := endingToString(c, "bad SMIMEA Certificate")
   1530 	if e3 != nil {
   1531 		return e3
   1532 	}
   1533 	rr.Certificate = s
   1534 	return nil
   1535 }
   1536 
   1537 func (rr *RFC3597) parse(c *zlexer, o string) *ParseError {
   1538 	l, _ := c.Next()
   1539 	if l.token != "\\#" {
   1540 		return &ParseError{"", "bad RFC3597 Rdata", l}
   1541 	}
   1542 
   1543 	c.Next() // zBlank
   1544 	l, _ = c.Next()
   1545 	rdlength, e := strconv.ParseUint(l.token, 10, 16)
   1546 	if e != nil || l.err {
   1547 		return &ParseError{"", "bad RFC3597 Rdata ", l}
   1548 	}
   1549 
   1550 	s, e1 := endingToString(c, "bad RFC3597 Rdata")
   1551 	if e1 != nil {
   1552 		return e1
   1553 	}
   1554 	if int(rdlength)*2 != len(s) {
   1555 		return &ParseError{"", "bad RFC3597 Rdata", l}
   1556 	}
   1557 	rr.Rdata = s
   1558 	return nil
   1559 }
   1560 
   1561 func (rr *SPF) parse(c *zlexer, o string) *ParseError {
   1562 	s, e := endingToTxtSlice(c, "bad SPF Txt")
   1563 	if e != nil {
   1564 		return e
   1565 	}
   1566 	rr.Txt = s
   1567 	return nil
   1568 }
   1569 
   1570 func (rr *AVC) parse(c *zlexer, o string) *ParseError {
   1571 	s, e := endingToTxtSlice(c, "bad AVC Txt")
   1572 	if e != nil {
   1573 		return e
   1574 	}
   1575 	rr.Txt = s
   1576 	return nil
   1577 }
   1578 
   1579 func (rr *TXT) parse(c *zlexer, o string) *ParseError {
   1580 	// no zBlank reading here, because all this rdata is TXT
   1581 	s, e := endingToTxtSlice(c, "bad TXT Txt")
   1582 	if e != nil {
   1583 		return e
   1584 	}
   1585 	rr.Txt = s
   1586 	return nil
   1587 }
   1588 
   1589 // identical to setTXT
   1590 func (rr *NINFO) parse(c *zlexer, o string) *ParseError {
   1591 	s, e := endingToTxtSlice(c, "bad NINFO ZSData")
   1592 	if e != nil {
   1593 		return e
   1594 	}
   1595 	rr.ZSData = s
   1596 	return nil
   1597 }
   1598 
   1599 func (rr *URI) parse(c *zlexer, o string) *ParseError {
   1600 	l, _ := c.Next()
   1601 	i, e := strconv.ParseUint(l.token, 10, 16)
   1602 	if e != nil || l.err {
   1603 		return &ParseError{"", "bad URI Priority", l}
   1604 	}
   1605 	rr.Priority = uint16(i)
   1606 	c.Next() // zBlank
   1607 	l, _ = c.Next()
   1608 	i, e1 := strconv.ParseUint(l.token, 10, 16)
   1609 	if e1 != nil || l.err {
   1610 		return &ParseError{"", "bad URI Weight", l}
   1611 	}
   1612 	rr.Weight = uint16(i)
   1613 
   1614 	c.Next() // zBlank
   1615 	s, e2 := endingToTxtSlice(c, "bad URI Target")
   1616 	if e2 != nil {
   1617 		return e2
   1618 	}
   1619 	if len(s) != 1 {
   1620 		return &ParseError{"", "bad URI Target", l}
   1621 	}
   1622 	rr.Target = s[0]
   1623 	return nil
   1624 }
   1625 
   1626 func (rr *DHCID) parse(c *zlexer, o string) *ParseError {
   1627 	// awesome record to parse!
   1628 	s, e := endingToString(c, "bad DHCID Digest")
   1629 	if e != nil {
   1630 		return e
   1631 	}
   1632 	rr.Digest = s
   1633 	return nil
   1634 }
   1635 
   1636 func (rr *NID) parse(c *zlexer, o string) *ParseError {
   1637 	l, _ := c.Next()
   1638 	i, e := strconv.ParseUint(l.token, 10, 16)
   1639 	if e != nil || l.err {
   1640 		return &ParseError{"", "bad NID Preference", l}
   1641 	}
   1642 	rr.Preference = uint16(i)
   1643 	c.Next()        // zBlank
   1644 	l, _ = c.Next() // zString
   1645 	u, e1 := stringToNodeID(l)
   1646 	if e1 != nil || l.err {
   1647 		return e1
   1648 	}
   1649 	rr.NodeID = u
   1650 	return slurpRemainder(c)
   1651 }
   1652 
   1653 func (rr *L32) parse(c *zlexer, o string) *ParseError {
   1654 	l, _ := c.Next()
   1655 	i, e := strconv.ParseUint(l.token, 10, 16)
   1656 	if e != nil || l.err {
   1657 		return &ParseError{"", "bad L32 Preference", l}
   1658 	}
   1659 	rr.Preference = uint16(i)
   1660 	c.Next()        // zBlank
   1661 	l, _ = c.Next() // zString
   1662 	rr.Locator32 = net.ParseIP(l.token)
   1663 	if rr.Locator32 == nil || l.err {
   1664 		return &ParseError{"", "bad L32 Locator", l}
   1665 	}
   1666 	return slurpRemainder(c)
   1667 }
   1668 
   1669 func (rr *LP) parse(c *zlexer, o string) *ParseError {
   1670 	l, _ := c.Next()
   1671 	i, e := strconv.ParseUint(l.token, 10, 16)
   1672 	if e != nil || l.err {
   1673 		return &ParseError{"", "bad LP Preference", l}
   1674 	}
   1675 	rr.Preference = uint16(i)
   1676 
   1677 	c.Next()        // zBlank
   1678 	l, _ = c.Next() // zString
   1679 	rr.Fqdn = l.token
   1680 	name, nameOk := toAbsoluteName(l.token, o)
   1681 	if l.err || !nameOk {
   1682 		return &ParseError{"", "bad LP Fqdn", l}
   1683 	}
   1684 	rr.Fqdn = name
   1685 	return slurpRemainder(c)
   1686 }
   1687 
   1688 func (rr *L64) parse(c *zlexer, o string) *ParseError {
   1689 	l, _ := c.Next()
   1690 	i, e := strconv.ParseUint(l.token, 10, 16)
   1691 	if e != nil || l.err {
   1692 		return &ParseError{"", "bad L64 Preference", l}
   1693 	}
   1694 	rr.Preference = uint16(i)
   1695 	c.Next()        // zBlank
   1696 	l, _ = c.Next() // zString
   1697 	u, e1 := stringToNodeID(l)
   1698 	if e1 != nil || l.err {
   1699 		return e1
   1700 	}
   1701 	rr.Locator64 = u
   1702 	return slurpRemainder(c)
   1703 }
   1704 
   1705 func (rr *UID) parse(c *zlexer, o string) *ParseError {
   1706 	l, _ := c.Next()
   1707 	i, e := strconv.ParseUint(l.token, 10, 32)
   1708 	if e != nil || l.err {
   1709 		return &ParseError{"", "bad UID Uid", l}
   1710 	}
   1711 	rr.Uid = uint32(i)
   1712 	return slurpRemainder(c)
   1713 }
   1714 
   1715 func (rr *GID) parse(c *zlexer, o string) *ParseError {
   1716 	l, _ := c.Next()
   1717 	i, e := strconv.ParseUint(l.token, 10, 32)
   1718 	if e != nil || l.err {
   1719 		return &ParseError{"", "bad GID Gid", l}
   1720 	}
   1721 	rr.Gid = uint32(i)
   1722 	return slurpRemainder(c)
   1723 }
   1724 
   1725 func (rr *UINFO) parse(c *zlexer, o string) *ParseError {
   1726 	s, e := endingToTxtSlice(c, "bad UINFO Uinfo")
   1727 	if e != nil {
   1728 		return e
   1729 	}
   1730 	if ln := len(s); ln == 0 {
   1731 		return nil
   1732 	}
   1733 	rr.Uinfo = s[0] // silently discard anything after the first character-string
   1734 	return nil
   1735 }
   1736 
   1737 func (rr *PX) parse(c *zlexer, o string) *ParseError {
   1738 	l, _ := c.Next()
   1739 	i, e := strconv.ParseUint(l.token, 10, 16)
   1740 	if e != nil || l.err {
   1741 		return &ParseError{"", "bad PX Preference", l}
   1742 	}
   1743 	rr.Preference = uint16(i)
   1744 
   1745 	c.Next()        // zBlank
   1746 	l, _ = c.Next() // zString
   1747 	rr.Map822 = l.token
   1748 	map822, map822Ok := toAbsoluteName(l.token, o)
   1749 	if l.err || !map822Ok {
   1750 		return &ParseError{"", "bad PX Map822", l}
   1751 	}
   1752 	rr.Map822 = map822
   1753 
   1754 	c.Next()        // zBlank
   1755 	l, _ = c.Next() // zString
   1756 	rr.Mapx400 = l.token
   1757 	mapx400, mapx400Ok := toAbsoluteName(l.token, o)
   1758 	if l.err || !mapx400Ok {
   1759 		return &ParseError{"", "bad PX Mapx400", l}
   1760 	}
   1761 	rr.Mapx400 = mapx400
   1762 	return slurpRemainder(c)
   1763 }
   1764 
   1765 func (rr *CAA) parse(c *zlexer, o string) *ParseError {
   1766 	l, _ := c.Next()
   1767 	i, e := strconv.ParseUint(l.token, 10, 8)
   1768 	if e != nil || l.err {
   1769 		return &ParseError{"", "bad CAA Flag", l}
   1770 	}
   1771 	rr.Flag = uint8(i)
   1772 
   1773 	c.Next()        // zBlank
   1774 	l, _ = c.Next() // zString
   1775 	if l.value != zString {
   1776 		return &ParseError{"", "bad CAA Tag", l}
   1777 	}
   1778 	rr.Tag = l.token
   1779 
   1780 	c.Next() // zBlank
   1781 	s, e1 := endingToTxtSlice(c, "bad CAA Value")
   1782 	if e1 != nil {
   1783 		return e1
   1784 	}
   1785 	if len(s) != 1 {
   1786 		return &ParseError{"", "bad CAA Value", l}
   1787 	}
   1788 	rr.Value = s[0]
   1789 	return nil
   1790 }
   1791 
   1792 func (rr *TKEY) parse(c *zlexer, o string) *ParseError {
   1793 	l, _ := c.Next()
   1794 
   1795 	// Algorithm
   1796 	if l.value != zString {
   1797 		return &ParseError{"", "bad TKEY algorithm", l}
   1798 	}
   1799 	rr.Algorithm = l.token
   1800 	c.Next() // zBlank
   1801 
   1802 	// Get the key length and key values
   1803 	l, _ = c.Next()
   1804 	i, e := strconv.ParseUint(l.token, 10, 8)
   1805 	if e != nil || l.err {
   1806 		return &ParseError{"", "bad TKEY key length", l}
   1807 	}
   1808 	rr.KeySize = uint16(i)
   1809 	c.Next() // zBlank
   1810 	l, _ = c.Next()
   1811 	if l.value != zString {
   1812 		return &ParseError{"", "bad TKEY key", l}
   1813 	}
   1814 	rr.Key = l.token
   1815 	c.Next() // zBlank
   1816 
   1817 	// Get the otherdata length and string data
   1818 	l, _ = c.Next()
   1819 	i, e1 := strconv.ParseUint(l.token, 10, 8)
   1820 	if e1 != nil || l.err {
   1821 		return &ParseError{"", "bad TKEY otherdata length", l}
   1822 	}
   1823 	rr.OtherLen = uint16(i)
   1824 	c.Next() // zBlank
   1825 	l, _ = c.Next()
   1826 	if l.value != zString {
   1827 		return &ParseError{"", "bad TKEY otherday", l}
   1828 	}
   1829 	rr.OtherData = l.token
   1830 	return nil
   1831 }
   1832 
   1833 func (rr *APL) parse(c *zlexer, o string) *ParseError {
   1834 	var prefixes []APLPrefix
   1835 
   1836 	for {
   1837 		l, _ := c.Next()
   1838 		if l.value == zNewline || l.value == zEOF {
   1839 			break
   1840 		}
   1841 		if l.value == zBlank && prefixes != nil {
   1842 			continue
   1843 		}
   1844 		if l.value != zString {
   1845 			return &ParseError{"", "unexpected APL field", l}
   1846 		}
   1847 
   1848 		// Expected format: [!]afi:address/prefix
   1849 
   1850 		colon := strings.IndexByte(l.token, ':')
   1851 		if colon == -1 {
   1852 			return &ParseError{"", "missing colon in APL field", l}
   1853 		}
   1854 
   1855 		family, cidr := l.token[:colon], l.token[colon+1:]
   1856 
   1857 		var negation bool
   1858 		if family != "" && family[0] == '!' {
   1859 			negation = true
   1860 			family = family[1:]
   1861 		}
   1862 
   1863 		afi, e := strconv.ParseUint(family, 10, 16)
   1864 		if e != nil {
   1865 			return &ParseError{"", "failed to parse APL family: " + e.Error(), l}
   1866 		}
   1867 		var addrLen int
   1868 		switch afi {
   1869 		case 1:
   1870 			addrLen = net.IPv4len
   1871 		case 2:
   1872 			addrLen = net.IPv6len
   1873 		default:
   1874 			return &ParseError{"", "unrecognized APL family", l}
   1875 		}
   1876 
   1877 		ip, subnet, e1 := net.ParseCIDR(cidr)
   1878 		if e1 != nil {
   1879 			return &ParseError{"", "failed to parse APL address: " + e1.Error(), l}
   1880 		}
   1881 		if !ip.Equal(subnet.IP) {
   1882 			return &ParseError{"", "extra bits in APL address", l}
   1883 		}
   1884 
   1885 		if len(subnet.IP) != addrLen {
   1886 			return &ParseError{"", "address mismatch with the APL family", l}
   1887 		}
   1888 
   1889 		prefixes = append(prefixes, APLPrefix{
   1890 			Negation: negation,
   1891 			Network:  *subnet,
   1892 		})
   1893 	}
   1894 
   1895 	rr.Prefixes = prefixes
   1896 	return nil
   1897 }