gtsocial-umbx

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

msg_helpers.go (22565B)


      1 package dns
      2 
      3 import (
      4 	"encoding/base32"
      5 	"encoding/base64"
      6 	"encoding/binary"
      7 	"encoding/hex"
      8 	"net"
      9 	"sort"
     10 	"strings"
     11 )
     12 
     13 // helper functions called from the generated zmsg.go
     14 
     15 // These function are named after the tag to help pack/unpack, if there is no tag it is the name
     16 // of the type they pack/unpack (string, int, etc). We prefix all with unpackData or packData, so packDataA or
     17 // packDataDomainName.
     18 
     19 func unpackDataA(msg []byte, off int) (net.IP, int, error) {
     20 	if off+net.IPv4len > len(msg) {
     21 		return nil, len(msg), &Error{err: "overflow unpacking a"}
     22 	}
     23 	a := append(make(net.IP, 0, net.IPv4len), msg[off:off+net.IPv4len]...)
     24 	off += net.IPv4len
     25 	return a, off, nil
     26 }
     27 
     28 func packDataA(a net.IP, msg []byte, off int) (int, error) {
     29 	switch len(a) {
     30 	case net.IPv4len, net.IPv6len:
     31 		// It must be a slice of 4, even if it is 16, we encode only the first 4
     32 		if off+net.IPv4len > len(msg) {
     33 			return len(msg), &Error{err: "overflow packing a"}
     34 		}
     35 
     36 		copy(msg[off:], a.To4())
     37 		off += net.IPv4len
     38 	case 0:
     39 		// Allowed, for dynamic updates.
     40 	default:
     41 		return len(msg), &Error{err: "overflow packing a"}
     42 	}
     43 	return off, nil
     44 }
     45 
     46 func unpackDataAAAA(msg []byte, off int) (net.IP, int, error) {
     47 	if off+net.IPv6len > len(msg) {
     48 		return nil, len(msg), &Error{err: "overflow unpacking aaaa"}
     49 	}
     50 	aaaa := append(make(net.IP, 0, net.IPv6len), msg[off:off+net.IPv6len]...)
     51 	off += net.IPv6len
     52 	return aaaa, off, nil
     53 }
     54 
     55 func packDataAAAA(aaaa net.IP, msg []byte, off int) (int, error) {
     56 	switch len(aaaa) {
     57 	case net.IPv6len:
     58 		if off+net.IPv6len > len(msg) {
     59 			return len(msg), &Error{err: "overflow packing aaaa"}
     60 		}
     61 
     62 		copy(msg[off:], aaaa)
     63 		off += net.IPv6len
     64 	case 0:
     65 		// Allowed, dynamic updates.
     66 	default:
     67 		return len(msg), &Error{err: "overflow packing aaaa"}
     68 	}
     69 	return off, nil
     70 }
     71 
     72 // unpackHeader unpacks an RR header, returning the offset to the end of the header and a
     73 // re-sliced msg according to the expected length of the RR.
     74 func unpackHeader(msg []byte, off int) (rr RR_Header, off1 int, truncmsg []byte, err error) {
     75 	hdr := RR_Header{}
     76 	if off == len(msg) {
     77 		return hdr, off, msg, nil
     78 	}
     79 
     80 	hdr.Name, off, err = UnpackDomainName(msg, off)
     81 	if err != nil {
     82 		return hdr, len(msg), msg, err
     83 	}
     84 	hdr.Rrtype, off, err = unpackUint16(msg, off)
     85 	if err != nil {
     86 		return hdr, len(msg), msg, err
     87 	}
     88 	hdr.Class, off, err = unpackUint16(msg, off)
     89 	if err != nil {
     90 		return hdr, len(msg), msg, err
     91 	}
     92 	hdr.Ttl, off, err = unpackUint32(msg, off)
     93 	if err != nil {
     94 		return hdr, len(msg), msg, err
     95 	}
     96 	hdr.Rdlength, off, err = unpackUint16(msg, off)
     97 	if err != nil {
     98 		return hdr, len(msg), msg, err
     99 	}
    100 	msg, err = truncateMsgFromRdlength(msg, off, hdr.Rdlength)
    101 	return hdr, off, msg, err
    102 }
    103 
    104 // packHeader packs an RR header, returning the offset to the end of the header.
    105 // See PackDomainName for documentation about the compression.
    106 func (hdr RR_Header) packHeader(msg []byte, off int, compression compressionMap, compress bool) (int, error) {
    107 	if off == len(msg) {
    108 		return off, nil
    109 	}
    110 
    111 	off, err := packDomainName(hdr.Name, msg, off, compression, compress)
    112 	if err != nil {
    113 		return len(msg), err
    114 	}
    115 	off, err = packUint16(hdr.Rrtype, msg, off)
    116 	if err != nil {
    117 		return len(msg), err
    118 	}
    119 	off, err = packUint16(hdr.Class, msg, off)
    120 	if err != nil {
    121 		return len(msg), err
    122 	}
    123 	off, err = packUint32(hdr.Ttl, msg, off)
    124 	if err != nil {
    125 		return len(msg), err
    126 	}
    127 	off, err = packUint16(0, msg, off) // The RDLENGTH field will be set later in packRR.
    128 	if err != nil {
    129 		return len(msg), err
    130 	}
    131 	return off, nil
    132 }
    133 
    134 // helper helper functions.
    135 
    136 // truncateMsgFromRdLength truncates msg to match the expected length of the RR.
    137 // Returns an error if msg is smaller than the expected size.
    138 func truncateMsgFromRdlength(msg []byte, off int, rdlength uint16) (truncmsg []byte, err error) {
    139 	lenrd := off + int(rdlength)
    140 	if lenrd > len(msg) {
    141 		return msg, &Error{err: "overflowing header size"}
    142 	}
    143 	return msg[:lenrd], nil
    144 }
    145 
    146 var base32HexNoPadEncoding = base32.HexEncoding.WithPadding(base32.NoPadding)
    147 
    148 func fromBase32(s []byte) (buf []byte, err error) {
    149 	for i, b := range s {
    150 		if b >= 'a' && b <= 'z' {
    151 			s[i] = b - 32
    152 		}
    153 	}
    154 	buflen := base32HexNoPadEncoding.DecodedLen(len(s))
    155 	buf = make([]byte, buflen)
    156 	n, err := base32HexNoPadEncoding.Decode(buf, s)
    157 	buf = buf[:n]
    158 	return
    159 }
    160 
    161 func toBase32(b []byte) string {
    162 	return base32HexNoPadEncoding.EncodeToString(b)
    163 }
    164 
    165 func fromBase64(s []byte) (buf []byte, err error) {
    166 	buflen := base64.StdEncoding.DecodedLen(len(s))
    167 	buf = make([]byte, buflen)
    168 	n, err := base64.StdEncoding.Decode(buf, s)
    169 	buf = buf[:n]
    170 	return
    171 }
    172 
    173 func toBase64(b []byte) string { return base64.StdEncoding.EncodeToString(b) }
    174 
    175 // dynamicUpdate returns true if the Rdlength is zero.
    176 func noRdata(h RR_Header) bool { return h.Rdlength == 0 }
    177 
    178 func unpackUint8(msg []byte, off int) (i uint8, off1 int, err error) {
    179 	if off+1 > len(msg) {
    180 		return 0, len(msg), &Error{err: "overflow unpacking uint8"}
    181 	}
    182 	return msg[off], off + 1, nil
    183 }
    184 
    185 func packUint8(i uint8, msg []byte, off int) (off1 int, err error) {
    186 	if off+1 > len(msg) {
    187 		return len(msg), &Error{err: "overflow packing uint8"}
    188 	}
    189 	msg[off] = i
    190 	return off + 1, nil
    191 }
    192 
    193 func unpackUint16(msg []byte, off int) (i uint16, off1 int, err error) {
    194 	if off+2 > len(msg) {
    195 		return 0, len(msg), &Error{err: "overflow unpacking uint16"}
    196 	}
    197 	return binary.BigEndian.Uint16(msg[off:]), off + 2, nil
    198 }
    199 
    200 func packUint16(i uint16, msg []byte, off int) (off1 int, err error) {
    201 	if off+2 > len(msg) {
    202 		return len(msg), &Error{err: "overflow packing uint16"}
    203 	}
    204 	binary.BigEndian.PutUint16(msg[off:], i)
    205 	return off + 2, nil
    206 }
    207 
    208 func unpackUint32(msg []byte, off int) (i uint32, off1 int, err error) {
    209 	if off+4 > len(msg) {
    210 		return 0, len(msg), &Error{err: "overflow unpacking uint32"}
    211 	}
    212 	return binary.BigEndian.Uint32(msg[off:]), off + 4, nil
    213 }
    214 
    215 func packUint32(i uint32, msg []byte, off int) (off1 int, err error) {
    216 	if off+4 > len(msg) {
    217 		return len(msg), &Error{err: "overflow packing uint32"}
    218 	}
    219 	binary.BigEndian.PutUint32(msg[off:], i)
    220 	return off + 4, nil
    221 }
    222 
    223 func unpackUint48(msg []byte, off int) (i uint64, off1 int, err error) {
    224 	if off+6 > len(msg) {
    225 		return 0, len(msg), &Error{err: "overflow unpacking uint64 as uint48"}
    226 	}
    227 	// Used in TSIG where the last 48 bits are occupied, so for now, assume a uint48 (6 bytes)
    228 	i = uint64(msg[off])<<40 | uint64(msg[off+1])<<32 | uint64(msg[off+2])<<24 | uint64(msg[off+3])<<16 |
    229 		uint64(msg[off+4])<<8 | uint64(msg[off+5])
    230 	off += 6
    231 	return i, off, nil
    232 }
    233 
    234 func packUint48(i uint64, msg []byte, off int) (off1 int, err error) {
    235 	if off+6 > len(msg) {
    236 		return len(msg), &Error{err: "overflow packing uint64 as uint48"}
    237 	}
    238 	msg[off] = byte(i >> 40)
    239 	msg[off+1] = byte(i >> 32)
    240 	msg[off+2] = byte(i >> 24)
    241 	msg[off+3] = byte(i >> 16)
    242 	msg[off+4] = byte(i >> 8)
    243 	msg[off+5] = byte(i)
    244 	off += 6
    245 	return off, nil
    246 }
    247 
    248 func unpackUint64(msg []byte, off int) (i uint64, off1 int, err error) {
    249 	if off+8 > len(msg) {
    250 		return 0, len(msg), &Error{err: "overflow unpacking uint64"}
    251 	}
    252 	return binary.BigEndian.Uint64(msg[off:]), off + 8, nil
    253 }
    254 
    255 func packUint64(i uint64, msg []byte, off int) (off1 int, err error) {
    256 	if off+8 > len(msg) {
    257 		return len(msg), &Error{err: "overflow packing uint64"}
    258 	}
    259 	binary.BigEndian.PutUint64(msg[off:], i)
    260 	off += 8
    261 	return off, nil
    262 }
    263 
    264 func unpackString(msg []byte, off int) (string, int, error) {
    265 	if off+1 > len(msg) {
    266 		return "", off, &Error{err: "overflow unpacking txt"}
    267 	}
    268 	l := int(msg[off])
    269 	off++
    270 	if off+l > len(msg) {
    271 		return "", off, &Error{err: "overflow unpacking txt"}
    272 	}
    273 	var s strings.Builder
    274 	consumed := 0
    275 	for i, b := range msg[off : off+l] {
    276 		switch {
    277 		case b == '"' || b == '\\':
    278 			if consumed == 0 {
    279 				s.Grow(l * 2)
    280 			}
    281 			s.Write(msg[off+consumed : off+i])
    282 			s.WriteByte('\\')
    283 			s.WriteByte(b)
    284 			consumed = i + 1
    285 		case b < ' ' || b > '~': // unprintable
    286 			if consumed == 0 {
    287 				s.Grow(l * 2)
    288 			}
    289 			s.Write(msg[off+consumed : off+i])
    290 			s.WriteString(escapeByte(b))
    291 			consumed = i + 1
    292 		}
    293 	}
    294 	if consumed == 0 { // no escaping needed
    295 		return string(msg[off : off+l]), off + l, nil
    296 	}
    297 	s.Write(msg[off+consumed : off+l])
    298 	return s.String(), off + l, nil
    299 }
    300 
    301 func packString(s string, msg []byte, off int) (int, error) {
    302 	off, err := packTxtString(s, msg, off)
    303 	if err != nil {
    304 		return len(msg), err
    305 	}
    306 	return off, nil
    307 }
    308 
    309 func unpackStringBase32(msg []byte, off, end int) (string, int, error) {
    310 	if end > len(msg) {
    311 		return "", len(msg), &Error{err: "overflow unpacking base32"}
    312 	}
    313 	s := toBase32(msg[off:end])
    314 	return s, end, nil
    315 }
    316 
    317 func packStringBase32(s string, msg []byte, off int) (int, error) {
    318 	b32, err := fromBase32([]byte(s))
    319 	if err != nil {
    320 		return len(msg), err
    321 	}
    322 	if off+len(b32) > len(msg) {
    323 		return len(msg), &Error{err: "overflow packing base32"}
    324 	}
    325 	copy(msg[off:off+len(b32)], b32)
    326 	off += len(b32)
    327 	return off, nil
    328 }
    329 
    330 func unpackStringBase64(msg []byte, off, end int) (string, int, error) {
    331 	// Rest of the RR is base64 encoded value, so we don't need an explicit length
    332 	// to be set. Thus far all RR's that have base64 encoded fields have those as their
    333 	// last one. What we do need is the end of the RR!
    334 	if end > len(msg) {
    335 		return "", len(msg), &Error{err: "overflow unpacking base64"}
    336 	}
    337 	s := toBase64(msg[off:end])
    338 	return s, end, nil
    339 }
    340 
    341 func packStringBase64(s string, msg []byte, off int) (int, error) {
    342 	b64, err := fromBase64([]byte(s))
    343 	if err != nil {
    344 		return len(msg), err
    345 	}
    346 	if off+len(b64) > len(msg) {
    347 		return len(msg), &Error{err: "overflow packing base64"}
    348 	}
    349 	copy(msg[off:off+len(b64)], b64)
    350 	off += len(b64)
    351 	return off, nil
    352 }
    353 
    354 func unpackStringHex(msg []byte, off, end int) (string, int, error) {
    355 	// Rest of the RR is hex encoded value, so we don't need an explicit length
    356 	// to be set. NSEC and TSIG have hex fields with a length field.
    357 	// What we do need is the end of the RR!
    358 	if end > len(msg) {
    359 		return "", len(msg), &Error{err: "overflow unpacking hex"}
    360 	}
    361 
    362 	s := hex.EncodeToString(msg[off:end])
    363 	return s, end, nil
    364 }
    365 
    366 func packStringHex(s string, msg []byte, off int) (int, error) {
    367 	h, err := hex.DecodeString(s)
    368 	if err != nil {
    369 		return len(msg), err
    370 	}
    371 	if off+len(h) > len(msg) {
    372 		return len(msg), &Error{err: "overflow packing hex"}
    373 	}
    374 	copy(msg[off:off+len(h)], h)
    375 	off += len(h)
    376 	return off, nil
    377 }
    378 
    379 func unpackStringAny(msg []byte, off, end int) (string, int, error) {
    380 	if end > len(msg) {
    381 		return "", len(msg), &Error{err: "overflow unpacking anything"}
    382 	}
    383 	return string(msg[off:end]), end, nil
    384 }
    385 
    386 func packStringAny(s string, msg []byte, off int) (int, error) {
    387 	if off+len(s) > len(msg) {
    388 		return len(msg), &Error{err: "overflow packing anything"}
    389 	}
    390 	copy(msg[off:off+len(s)], s)
    391 	off += len(s)
    392 	return off, nil
    393 }
    394 
    395 func unpackStringTxt(msg []byte, off int) ([]string, int, error) {
    396 	txt, off, err := unpackTxt(msg, off)
    397 	if err != nil {
    398 		return nil, len(msg), err
    399 	}
    400 	return txt, off, nil
    401 }
    402 
    403 func packStringTxt(s []string, msg []byte, off int) (int, error) {
    404 	off, err := packTxt(s, msg, off)
    405 	if err != nil {
    406 		return len(msg), err
    407 	}
    408 	return off, nil
    409 }
    410 
    411 func unpackDataOpt(msg []byte, off int) ([]EDNS0, int, error) {
    412 	var edns []EDNS0
    413 Option:
    414 	var code uint16
    415 	if off+4 > len(msg) {
    416 		return nil, len(msg), &Error{err: "overflow unpacking opt"}
    417 	}
    418 	code = binary.BigEndian.Uint16(msg[off:])
    419 	off += 2
    420 	optlen := binary.BigEndian.Uint16(msg[off:])
    421 	off += 2
    422 	if off+int(optlen) > len(msg) {
    423 		return nil, len(msg), &Error{err: "overflow unpacking opt"}
    424 	}
    425 	e := makeDataOpt(code)
    426 	if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
    427 		return nil, len(msg), err
    428 	}
    429 	edns = append(edns, e)
    430 	off += int(optlen)
    431 
    432 	if off < len(msg) {
    433 		goto Option
    434 	}
    435 
    436 	return edns, off, nil
    437 }
    438 
    439 func packDataOpt(options []EDNS0, msg []byte, off int) (int, error) {
    440 	for _, el := range options {
    441 		b, err := el.pack()
    442 		if err != nil || off+4 > len(msg) {
    443 			return len(msg), &Error{err: "overflow packing opt"}
    444 		}
    445 		binary.BigEndian.PutUint16(msg[off:], el.Option())      // Option code
    446 		binary.BigEndian.PutUint16(msg[off+2:], uint16(len(b))) // Length
    447 		off += 4
    448 		if off+len(b) > len(msg) {
    449 			return len(msg), &Error{err: "overflow packing opt"}
    450 		}
    451 		// Actual data
    452 		copy(msg[off:off+len(b)], b)
    453 		off += len(b)
    454 	}
    455 	return off, nil
    456 }
    457 
    458 func unpackStringOctet(msg []byte, off int) (string, int, error) {
    459 	s := string(msg[off:])
    460 	return s, len(msg), nil
    461 }
    462 
    463 func packStringOctet(s string, msg []byte, off int) (int, error) {
    464 	txtTmp := make([]byte, 256*4+1)
    465 	off, err := packOctetString(s, msg, off, txtTmp)
    466 	if err != nil {
    467 		return len(msg), err
    468 	}
    469 	return off, nil
    470 }
    471 
    472 func unpackDataNsec(msg []byte, off int) ([]uint16, int, error) {
    473 	var nsec []uint16
    474 	length, window, lastwindow := 0, 0, -1
    475 	for off < len(msg) {
    476 		if off+2 > len(msg) {
    477 			return nsec, len(msg), &Error{err: "overflow unpacking NSEC(3)"}
    478 		}
    479 		window = int(msg[off])
    480 		length = int(msg[off+1])
    481 		off += 2
    482 		if window <= lastwindow {
    483 			// RFC 4034: Blocks are present in the NSEC RR RDATA in
    484 			// increasing numerical order.
    485 			return nsec, len(msg), &Error{err: "out of order NSEC(3) block in type bitmap"}
    486 		}
    487 		if length == 0 {
    488 			// RFC 4034: Blocks with no types present MUST NOT be included.
    489 			return nsec, len(msg), &Error{err: "empty NSEC(3) block in type bitmap"}
    490 		}
    491 		if length > 32 {
    492 			return nsec, len(msg), &Error{err: "NSEC(3) block too long in type bitmap"}
    493 		}
    494 		if off+length > len(msg) {
    495 			return nsec, len(msg), &Error{err: "overflowing NSEC(3) block in type bitmap"}
    496 		}
    497 
    498 		// Walk the bytes in the window and extract the type bits
    499 		for j, b := range msg[off : off+length] {
    500 			// Check the bits one by one, and set the type
    501 			if b&0x80 == 0x80 {
    502 				nsec = append(nsec, uint16(window*256+j*8+0))
    503 			}
    504 			if b&0x40 == 0x40 {
    505 				nsec = append(nsec, uint16(window*256+j*8+1))
    506 			}
    507 			if b&0x20 == 0x20 {
    508 				nsec = append(nsec, uint16(window*256+j*8+2))
    509 			}
    510 			if b&0x10 == 0x10 {
    511 				nsec = append(nsec, uint16(window*256+j*8+3))
    512 			}
    513 			if b&0x8 == 0x8 {
    514 				nsec = append(nsec, uint16(window*256+j*8+4))
    515 			}
    516 			if b&0x4 == 0x4 {
    517 				nsec = append(nsec, uint16(window*256+j*8+5))
    518 			}
    519 			if b&0x2 == 0x2 {
    520 				nsec = append(nsec, uint16(window*256+j*8+6))
    521 			}
    522 			if b&0x1 == 0x1 {
    523 				nsec = append(nsec, uint16(window*256+j*8+7))
    524 			}
    525 		}
    526 		off += length
    527 		lastwindow = window
    528 	}
    529 	return nsec, off, nil
    530 }
    531 
    532 // typeBitMapLen is a helper function which computes the "maximum" length of
    533 // a the NSEC Type BitMap field.
    534 func typeBitMapLen(bitmap []uint16) int {
    535 	var l int
    536 	var lastwindow, lastlength uint16
    537 	for _, t := range bitmap {
    538 		window := t / 256
    539 		length := (t-window*256)/8 + 1
    540 		if window > lastwindow && lastlength != 0 { // New window, jump to the new offset
    541 			l += int(lastlength) + 2
    542 			lastlength = 0
    543 		}
    544 		if window < lastwindow || length < lastlength {
    545 			// packDataNsec would return Error{err: "nsec bits out of order"} here, but
    546 			// when computing the length, we want do be liberal.
    547 			continue
    548 		}
    549 		lastwindow, lastlength = window, length
    550 	}
    551 	l += int(lastlength) + 2
    552 	return l
    553 }
    554 
    555 func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
    556 	if len(bitmap) == 0 {
    557 		return off, nil
    558 	}
    559 	if off > len(msg) {
    560 		return off, &Error{err: "overflow packing nsec"}
    561 	}
    562 	toZero := msg[off:]
    563 	if maxLen := typeBitMapLen(bitmap); maxLen < len(toZero) {
    564 		toZero = toZero[:maxLen]
    565 	}
    566 	for i := range toZero {
    567 		toZero[i] = 0
    568 	}
    569 	var lastwindow, lastlength uint16
    570 	for _, t := range bitmap {
    571 		window := t / 256
    572 		length := (t-window*256)/8 + 1
    573 		if window > lastwindow && lastlength != 0 { // New window, jump to the new offset
    574 			off += int(lastlength) + 2
    575 			lastlength = 0
    576 		}
    577 		if window < lastwindow || length < lastlength {
    578 			return len(msg), &Error{err: "nsec bits out of order"}
    579 		}
    580 		if off+2+int(length) > len(msg) {
    581 			return len(msg), &Error{err: "overflow packing nsec"}
    582 		}
    583 		// Setting the window #
    584 		msg[off] = byte(window)
    585 		// Setting the octets length
    586 		msg[off+1] = byte(length)
    587 		// Setting the bit value for the type in the right octet
    588 		msg[off+1+int(length)] |= byte(1 << (7 - t%8))
    589 		lastwindow, lastlength = window, length
    590 	}
    591 	off += int(lastlength) + 2
    592 	return off, nil
    593 }
    594 
    595 func unpackDataSVCB(msg []byte, off int) ([]SVCBKeyValue, int, error) {
    596 	var xs []SVCBKeyValue
    597 	var code uint16
    598 	var length uint16
    599 	var err error
    600 	for off < len(msg) {
    601 		code, off, err = unpackUint16(msg, off)
    602 		if err != nil {
    603 			return nil, len(msg), &Error{err: "overflow unpacking SVCB"}
    604 		}
    605 		length, off, err = unpackUint16(msg, off)
    606 		if err != nil || off+int(length) > len(msg) {
    607 			return nil, len(msg), &Error{err: "overflow unpacking SVCB"}
    608 		}
    609 		e := makeSVCBKeyValue(SVCBKey(code))
    610 		if e == nil {
    611 			return nil, len(msg), &Error{err: "bad SVCB key"}
    612 		}
    613 		if err := e.unpack(msg[off : off+int(length)]); err != nil {
    614 			return nil, len(msg), err
    615 		}
    616 		if len(xs) > 0 && e.Key() <= xs[len(xs)-1].Key() {
    617 			return nil, len(msg), &Error{err: "SVCB keys not in strictly increasing order"}
    618 		}
    619 		xs = append(xs, e)
    620 		off += int(length)
    621 	}
    622 	return xs, off, nil
    623 }
    624 
    625 func packDataSVCB(pairs []SVCBKeyValue, msg []byte, off int) (int, error) {
    626 	pairs = cloneSlice(pairs)
    627 	sort.Slice(pairs, func(i, j int) bool {
    628 		return pairs[i].Key() < pairs[j].Key()
    629 	})
    630 	prev := svcb_RESERVED
    631 	for _, el := range pairs {
    632 		if el.Key() == prev {
    633 			return len(msg), &Error{err: "repeated SVCB keys are not allowed"}
    634 		}
    635 		prev = el.Key()
    636 		packed, err := el.pack()
    637 		if err != nil {
    638 			return len(msg), err
    639 		}
    640 		off, err = packUint16(uint16(el.Key()), msg, off)
    641 		if err != nil {
    642 			return len(msg), &Error{err: "overflow packing SVCB"}
    643 		}
    644 		off, err = packUint16(uint16(len(packed)), msg, off)
    645 		if err != nil || off+len(packed) > len(msg) {
    646 			return len(msg), &Error{err: "overflow packing SVCB"}
    647 		}
    648 		copy(msg[off:off+len(packed)], packed)
    649 		off += len(packed)
    650 	}
    651 	return off, nil
    652 }
    653 
    654 func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) {
    655 	var (
    656 		servers []string
    657 		s       string
    658 		err     error
    659 	)
    660 	if end > len(msg) {
    661 		return nil, len(msg), &Error{err: "overflow unpacking domain names"}
    662 	}
    663 	for off < end {
    664 		s, off, err = UnpackDomainName(msg, off)
    665 		if err != nil {
    666 			return servers, len(msg), err
    667 		}
    668 		servers = append(servers, s)
    669 	}
    670 	return servers, off, nil
    671 }
    672 
    673 func packDataDomainNames(names []string, msg []byte, off int, compression compressionMap, compress bool) (int, error) {
    674 	var err error
    675 	for _, name := range names {
    676 		off, err = packDomainName(name, msg, off, compression, compress)
    677 		if err != nil {
    678 			return len(msg), err
    679 		}
    680 	}
    681 	return off, nil
    682 }
    683 
    684 func packDataApl(data []APLPrefix, msg []byte, off int) (int, error) {
    685 	var err error
    686 	for i := range data {
    687 		off, err = packDataAplPrefix(&data[i], msg, off)
    688 		if err != nil {
    689 			return len(msg), err
    690 		}
    691 	}
    692 	return off, nil
    693 }
    694 
    695 func packDataAplPrefix(p *APLPrefix, msg []byte, off int) (int, error) {
    696 	if len(p.Network.IP) != len(p.Network.Mask) {
    697 		return len(msg), &Error{err: "address and mask lengths don't match"}
    698 	}
    699 
    700 	var err error
    701 	prefix, _ := p.Network.Mask.Size()
    702 	addr := p.Network.IP.Mask(p.Network.Mask)[:(prefix+7)/8]
    703 
    704 	switch len(p.Network.IP) {
    705 	case net.IPv4len:
    706 		off, err = packUint16(1, msg, off)
    707 	case net.IPv6len:
    708 		off, err = packUint16(2, msg, off)
    709 	default:
    710 		err = &Error{err: "unrecognized address family"}
    711 	}
    712 	if err != nil {
    713 		return len(msg), err
    714 	}
    715 
    716 	off, err = packUint8(uint8(prefix), msg, off)
    717 	if err != nil {
    718 		return len(msg), err
    719 	}
    720 
    721 	var n uint8
    722 	if p.Negation {
    723 		n = 0x80
    724 	}
    725 
    726 	// trim trailing zero bytes as specified in RFC3123 Sections 4.1 and 4.2.
    727 	i := len(addr) - 1
    728 	for ; i >= 0 && addr[i] == 0; i-- {
    729 	}
    730 	addr = addr[:i+1]
    731 
    732 	adflen := uint8(len(addr)) & 0x7f
    733 	off, err = packUint8(n|adflen, msg, off)
    734 	if err != nil {
    735 		return len(msg), err
    736 	}
    737 
    738 	if off+len(addr) > len(msg) {
    739 		return len(msg), &Error{err: "overflow packing APL prefix"}
    740 	}
    741 	off += copy(msg[off:], addr)
    742 
    743 	return off, nil
    744 }
    745 
    746 func unpackDataApl(msg []byte, off int) ([]APLPrefix, int, error) {
    747 	var result []APLPrefix
    748 	for off < len(msg) {
    749 		prefix, end, err := unpackDataAplPrefix(msg, off)
    750 		if err != nil {
    751 			return nil, len(msg), err
    752 		}
    753 		off = end
    754 		result = append(result, prefix)
    755 	}
    756 	return result, off, nil
    757 }
    758 
    759 func unpackDataAplPrefix(msg []byte, off int) (APLPrefix, int, error) {
    760 	family, off, err := unpackUint16(msg, off)
    761 	if err != nil {
    762 		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"}
    763 	}
    764 	prefix, off, err := unpackUint8(msg, off)
    765 	if err != nil {
    766 		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"}
    767 	}
    768 	nlen, off, err := unpackUint8(msg, off)
    769 	if err != nil {
    770 		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"}
    771 	}
    772 
    773 	var ip []byte
    774 	switch family {
    775 	case 1:
    776 		ip = make([]byte, net.IPv4len)
    777 	case 2:
    778 		ip = make([]byte, net.IPv6len)
    779 	default:
    780 		return APLPrefix{}, len(msg), &Error{err: "unrecognized APL address family"}
    781 	}
    782 	if int(prefix) > 8*len(ip) {
    783 		return APLPrefix{}, len(msg), &Error{err: "APL prefix too long"}
    784 	}
    785 	afdlen := int(nlen & 0x7f)
    786 	if afdlen > len(ip) {
    787 		return APLPrefix{}, len(msg), &Error{err: "APL length too long"}
    788 	}
    789 	if off+afdlen > len(msg) {
    790 		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL address"}
    791 	}
    792 
    793 	// Address MUST NOT contain trailing zero bytes per RFC3123 Sections 4.1 and 4.2.
    794 	off += copy(ip, msg[off:off+afdlen])
    795 	if afdlen > 0 {
    796 		last := ip[afdlen-1]
    797 		if last == 0 {
    798 			return APLPrefix{}, len(msg), &Error{err: "extra APL address bits"}
    799 		}
    800 	}
    801 	ipnet := net.IPNet{
    802 		IP:   ip,
    803 		Mask: net.CIDRMask(int(prefix), 8*len(ip)),
    804 	}
    805 
    806 	return APLPrefix{
    807 		Negation: (nlen & 0x80) != 0,
    808 		Network:  ipnet,
    809 	}, off, nil
    810 }
    811 
    812 func unpackIPSECGateway(msg []byte, off int, gatewayType uint8) (net.IP, string, int, error) {
    813 	var retAddr net.IP
    814 	var retString string
    815 	var err error
    816 
    817 	switch gatewayType {
    818 	case IPSECGatewayNone: // do nothing
    819 	case IPSECGatewayIPv4:
    820 		retAddr, off, err = unpackDataA(msg, off)
    821 	case IPSECGatewayIPv6:
    822 		retAddr, off, err = unpackDataAAAA(msg, off)
    823 	case IPSECGatewayHost:
    824 		retString, off, err = UnpackDomainName(msg, off)
    825 	}
    826 
    827 	return retAddr, retString, off, err
    828 }
    829 
    830 func packIPSECGateway(gatewayAddr net.IP, gatewayString string, msg []byte, off int, gatewayType uint8, compression compressionMap, compress bool) (int, error) {
    831 	var err error
    832 
    833 	switch gatewayType {
    834 	case IPSECGatewayNone: // do nothing
    835 	case IPSECGatewayIPv4:
    836 		off, err = packDataA(gatewayAddr, msg, off)
    837 	case IPSECGatewayIPv6:
    838 		off, err = packDataAAAA(gatewayAddr, msg, off)
    839 	case IPSECGatewayHost:
    840 		off, err = packDomainName(gatewayString, msg, off, compression, compress)
    841 	}
    842 
    843 	return off, err
    844 }