1package dns
2
3import (
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
19func 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
28func 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
46func 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
55func 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.
74func 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.
106func (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.
138func 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
146var base32HexNoPadEncoding = base32.HexEncoding.WithPadding(base32.NoPadding)
147
148func 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
161func toBase32(b []byte) string {
162	return base32HexNoPadEncoding.EncodeToString(b)
163}
164
165func 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
173func toBase64(b []byte) string { return base64.StdEncoding.EncodeToString(b) }
174
175// dynamicUpdate returns true if the Rdlength is zero.
176func noRdata(h RR_Header) bool { return h.Rdlength == 0 }
177
178func 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
185func 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
193func 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
200func 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
208func 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
215func 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
223func 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
234func 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
248func 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
255func 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
264func 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
301func packString(s string, msg []byte, off int) (int, error) {
302	txtTmp := make([]byte, 256*4+1)
303	off, err := packTxtString(s, msg, off, txtTmp)
304	if err != nil {
305		return len(msg), err
306	}
307	return off, nil
308}
309
310func unpackStringBase32(msg []byte, off, end int) (string, int, error) {
311	if end > len(msg) {
312		return "", len(msg), &Error{err: "overflow unpacking base32"}
313	}
314	s := toBase32(msg[off:end])
315	return s, end, nil
316}
317
318func packStringBase32(s string, msg []byte, off int) (int, error) {
319	b32, err := fromBase32([]byte(s))
320	if err != nil {
321		return len(msg), err
322	}
323	if off+len(b32) > len(msg) {
324		return len(msg), &Error{err: "overflow packing base32"}
325	}
326	copy(msg[off:off+len(b32)], b32)
327	off += len(b32)
328	return off, nil
329}
330
331func unpackStringBase64(msg []byte, off, end int) (string, int, error) {
332	// Rest of the RR is base64 encoded value, so we don't need an explicit length
333	// to be set. Thus far all RR's that have base64 encoded fields have those as their
334	// last one. What we do need is the end of the RR!
335	if end > len(msg) {
336		return "", len(msg), &Error{err: "overflow unpacking base64"}
337	}
338	s := toBase64(msg[off:end])
339	return s, end, nil
340}
341
342func packStringBase64(s string, msg []byte, off int) (int, error) {
343	b64, err := fromBase64([]byte(s))
344	if err != nil {
345		return len(msg), err
346	}
347	if off+len(b64) > len(msg) {
348		return len(msg), &Error{err: "overflow packing base64"}
349	}
350	copy(msg[off:off+len(b64)], b64)
351	off += len(b64)
352	return off, nil
353}
354
355func unpackStringHex(msg []byte, off, end int) (string, int, error) {
356	// Rest of the RR is hex encoded value, so we don't need an explicit length
357	// to be set. NSEC and TSIG have hex fields with a length field.
358	// What we do need is the end of the RR!
359	if end > len(msg) {
360		return "", len(msg), &Error{err: "overflow unpacking hex"}
361	}
362
363	s := hex.EncodeToString(msg[off:end])
364	return s, end, nil
365}
366
367func packStringHex(s string, msg []byte, off int) (int, error) {
368	h, err := hex.DecodeString(s)
369	if err != nil {
370		return len(msg), err
371	}
372	if off+len(h) > len(msg) {
373		return len(msg), &Error{err: "overflow packing hex"}
374	}
375	copy(msg[off:off+len(h)], h)
376	off += len(h)
377	return off, nil
378}
379
380func unpackStringAny(msg []byte, off, end int) (string, int, error) {
381	if end > len(msg) {
382		return "", len(msg), &Error{err: "overflow unpacking anything"}
383	}
384	return string(msg[off:end]), end, nil
385}
386
387func packStringAny(s string, msg []byte, off int) (int, error) {
388	if off+len(s) > len(msg) {
389		return len(msg), &Error{err: "overflow packing anything"}
390	}
391	copy(msg[off:off+len(s)], s)
392	off += len(s)
393	return off, nil
394}
395
396func unpackStringTxt(msg []byte, off int) ([]string, int, error) {
397	txt, off, err := unpackTxt(msg, off)
398	if err != nil {
399		return nil, len(msg), err
400	}
401	return txt, off, nil
402}
403
404func packStringTxt(s []string, msg []byte, off int) (int, error) {
405	txtTmp := make([]byte, 256*4+1) // If the whole string consists out of \DDD we need this many.
406	off, err := packTxt(s, msg, off, txtTmp)
407	if err != nil {
408		return len(msg), err
409	}
410	return off, nil
411}
412
413func unpackDataOpt(msg []byte, off int) ([]EDNS0, int, error) {
414	var edns []EDNS0
415Option:
416	var code uint16
417	if off+4 > len(msg) {
418		return nil, len(msg), &Error{err: "overflow unpacking opt"}
419	}
420	code = binary.BigEndian.Uint16(msg[off:])
421	off += 2
422	optlen := binary.BigEndian.Uint16(msg[off:])
423	off += 2
424	if off+int(optlen) > len(msg) {
425		return nil, len(msg), &Error{err: "overflow unpacking opt"}
426	}
427	e := makeDataOpt(code)
428	if err := e.unpack(msg[off : off+int(optlen)]); err != nil {
429		return nil, len(msg), err
430	}
431	edns = append(edns, e)
432	off += int(optlen)
433
434	if off < len(msg) {
435		goto Option
436	}
437
438	return edns, off, nil
439}
440
441func packDataOpt(options []EDNS0, msg []byte, off int) (int, error) {
442	for _, el := range options {
443		b, err := el.pack()
444		if err != nil || off+4 > len(msg) {
445			return len(msg), &Error{err: "overflow packing opt"}
446		}
447		binary.BigEndian.PutUint16(msg[off:], el.Option())      // Option code
448		binary.BigEndian.PutUint16(msg[off+2:], uint16(len(b))) // Length
449		off += 4
450		if off+len(b) > len(msg) {
451			return len(msg), &Error{err: "overflow packing opt"}
452		}
453		// Actual data
454		copy(msg[off:off+len(b)], b)
455		off += len(b)
456	}
457	return off, nil
458}
459
460func unpackStringOctet(msg []byte, off int) (string, int, error) {
461	s := string(msg[off:])
462	return s, len(msg), nil
463}
464
465func packStringOctet(s string, msg []byte, off int) (int, error) {
466	txtTmp := make([]byte, 256*4+1)
467	off, err := packOctetString(s, msg, off, txtTmp)
468	if err != nil {
469		return len(msg), err
470	}
471	return off, nil
472}
473
474func unpackDataNsec(msg []byte, off int) ([]uint16, int, error) {
475	var nsec []uint16
476	length, window, lastwindow := 0, 0, -1
477	for off < len(msg) {
478		if off+2 > len(msg) {
479			return nsec, len(msg), &Error{err: "overflow unpacking nsecx"}
480		}
481		window = int(msg[off])
482		length = int(msg[off+1])
483		off += 2
484		if window <= lastwindow {
485			// RFC 4034: Blocks are present in the NSEC RR RDATA in
486			// increasing numerical order.
487			return nsec, len(msg), &Error{err: "out of order NSEC block"}
488		}
489		if length == 0 {
490			// RFC 4034: Blocks with no types present MUST NOT be included.
491			return nsec, len(msg), &Error{err: "empty NSEC block"}
492		}
493		if length > 32 {
494			return nsec, len(msg), &Error{err: "NSEC block too long"}
495		}
496		if off+length > len(msg) {
497			return nsec, len(msg), &Error{err: "overflowing NSEC block"}
498		}
499
500		// Walk the bytes in the window and extract the type bits
501		for j, b := range msg[off : off+length] {
502			// Check the bits one by one, and set the type
503			if b&0x80 == 0x80 {
504				nsec = append(nsec, uint16(window*256+j*8+0))
505			}
506			if b&0x40 == 0x40 {
507				nsec = append(nsec, uint16(window*256+j*8+1))
508			}
509			if b&0x20 == 0x20 {
510				nsec = append(nsec, uint16(window*256+j*8+2))
511			}
512			if b&0x10 == 0x10 {
513				nsec = append(nsec, uint16(window*256+j*8+3))
514			}
515			if b&0x8 == 0x8 {
516				nsec = append(nsec, uint16(window*256+j*8+4))
517			}
518			if b&0x4 == 0x4 {
519				nsec = append(nsec, uint16(window*256+j*8+5))
520			}
521			if b&0x2 == 0x2 {
522				nsec = append(nsec, uint16(window*256+j*8+6))
523			}
524			if b&0x1 == 0x1 {
525				nsec = append(nsec, uint16(window*256+j*8+7))
526			}
527		}
528		off += length
529		lastwindow = window
530	}
531	return nsec, off, nil
532}
533
534// typeBitMapLen is a helper function which computes the "maximum" length of
535// a the NSEC Type BitMap field.
536func typeBitMapLen(bitmap []uint16) int {
537	var l int
538	var lastwindow, lastlength uint16
539	for _, t := range bitmap {
540		window := t / 256
541		length := (t-window*256)/8 + 1
542		if window > lastwindow && lastlength != 0 { // New window, jump to the new offset
543			l += int(lastlength) + 2
544			lastlength = 0
545		}
546		if window < lastwindow || length < lastlength {
547			// packDataNsec would return Error{err: "nsec bits out of order"} here, but
548			// when computing the length, we want do be liberal.
549			continue
550		}
551		lastwindow, lastlength = window, length
552	}
553	l += int(lastlength) + 2
554	return l
555}
556
557func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) {
558	if len(bitmap) == 0 {
559		return off, nil
560	}
561	var lastwindow, lastlength uint16
562	for _, t := range bitmap {
563		window := t / 256
564		length := (t-window*256)/8 + 1
565		if window > lastwindow && lastlength != 0 { // New window, jump to the new offset
566			off += int(lastlength) + 2
567			lastlength = 0
568		}
569		if window < lastwindow || length < lastlength {
570			return len(msg), &Error{err: "nsec bits out of order"}
571		}
572		if off+2+int(length) > len(msg) {
573			return len(msg), &Error{err: "overflow packing nsec"}
574		}
575		// Setting the window #
576		msg[off] = byte(window)
577		// Setting the octets length
578		msg[off+1] = byte(length)
579		// Setting the bit value for the type in the right octet
580		msg[off+1+int(length)] |= byte(1 << (7 - t%8))
581		lastwindow, lastlength = window, length
582	}
583	off += int(lastlength) + 2
584	return off, nil
585}
586
587func unpackDataSVCB(msg []byte, off int) ([]SVCBKeyValue, int, error) {
588	var xs []SVCBKeyValue
589	var code uint16
590	var length uint16
591	var err error
592	for off < len(msg) {
593		code, off, err = unpackUint16(msg, off)
594		if err != nil {
595			return nil, len(msg), &Error{err: "overflow unpacking SVCB"}
596		}
597		length, off, err = unpackUint16(msg, off)
598		if err != nil || off+int(length) > len(msg) {
599			return nil, len(msg), &Error{err: "overflow unpacking SVCB"}
600		}
601		e := makeSVCBKeyValue(SVCBKey(code))
602		if e == nil {
603			return nil, len(msg), &Error{err: "bad SVCB key"}
604		}
605		if err := e.unpack(msg[off : off+int(length)]); err != nil {
606			return nil, len(msg), err
607		}
608		if len(xs) > 0 && e.Key() <= xs[len(xs)-1].Key() {
609			return nil, len(msg), &Error{err: "SVCB keys not in strictly increasing order"}
610		}
611		xs = append(xs, e)
612		off += int(length)
613	}
614	return xs, off, nil
615}
616
617func packDataSVCB(pairs []SVCBKeyValue, msg []byte, off int) (int, error) {
618	pairs = append([]SVCBKeyValue(nil), pairs...)
619	sort.Slice(pairs, func(i, j int) bool {
620		return pairs[i].Key() < pairs[j].Key()
621	})
622	prev := svcb_RESERVED
623	for _, el := range pairs {
624		if el.Key() == prev {
625			return len(msg), &Error{err: "repeated SVCB keys are not allowed"}
626		}
627		prev = el.Key()
628		packed, err := el.pack()
629		if err != nil {
630			return len(msg), err
631		}
632		off, err = packUint16(uint16(el.Key()), msg, off)
633		if err != nil {
634			return len(msg), &Error{err: "overflow packing SVCB"}
635		}
636		off, err = packUint16(uint16(len(packed)), msg, off)
637		if err != nil || off+len(packed) > len(msg) {
638			return len(msg), &Error{err: "overflow packing SVCB"}
639		}
640		copy(msg[off:off+len(packed)], packed)
641		off += len(packed)
642	}
643	return off, nil
644}
645
646func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) {
647	var (
648		servers []string
649		s       string
650		err     error
651	)
652	if end > len(msg) {
653		return nil, len(msg), &Error{err: "overflow unpacking domain names"}
654	}
655	for off < end {
656		s, off, err = UnpackDomainName(msg, off)
657		if err != nil {
658			return servers, len(msg), err
659		}
660		servers = append(servers, s)
661	}
662	return servers, off, nil
663}
664
665func packDataDomainNames(names []string, msg []byte, off int, compression compressionMap, compress bool) (int, error) {
666	var err error
667	for _, name := range names {
668		off, err = packDomainName(name, msg, off, compression, compress)
669		if err != nil {
670			return len(msg), err
671		}
672	}
673	return off, nil
674}
675
676func packDataApl(data []APLPrefix, msg []byte, off int) (int, error) {
677	var err error
678	for i := range data {
679		off, err = packDataAplPrefix(&data[i], msg, off)
680		if err != nil {
681			return len(msg), err
682		}
683	}
684	return off, nil
685}
686
687func packDataAplPrefix(p *APLPrefix, msg []byte, off int) (int, error) {
688	if len(p.Network.IP) != len(p.Network.Mask) {
689		return len(msg), &Error{err: "address and mask lengths don't match"}
690	}
691
692	var err error
693	prefix, _ := p.Network.Mask.Size()
694	addr := p.Network.IP.Mask(p.Network.Mask)[:(prefix+7)/8]
695
696	switch len(p.Network.IP) {
697	case net.IPv4len:
698		off, err = packUint16(1, msg, off)
699	case net.IPv6len:
700		off, err = packUint16(2, msg, off)
701	default:
702		err = &Error{err: "unrecognized address family"}
703	}
704	if err != nil {
705		return len(msg), err
706	}
707
708	off, err = packUint8(uint8(prefix), msg, off)
709	if err != nil {
710		return len(msg), err
711	}
712
713	var n uint8
714	if p.Negation {
715		n = 0x80
716	}
717
718	// trim trailing zero bytes as specified in RFC3123 Sections 4.1 and 4.2.
719	i := len(addr) - 1
720	for ; i >= 0 && addr[i] == 0; i-- {
721	}
722	addr = addr[:i+1]
723
724	adflen := uint8(len(addr)) & 0x7f
725	off, err = packUint8(n|adflen, msg, off)
726	if err != nil {
727		return len(msg), err
728	}
729
730	if off+len(addr) > len(msg) {
731		return len(msg), &Error{err: "overflow packing APL prefix"}
732	}
733	off += copy(msg[off:], addr)
734
735	return off, nil
736}
737
738func unpackDataApl(msg []byte, off int) ([]APLPrefix, int, error) {
739	var result []APLPrefix
740	for off < len(msg) {
741		prefix, end, err := unpackDataAplPrefix(msg, off)
742		if err != nil {
743			return nil, len(msg), err
744		}
745		off = end
746		result = append(result, prefix)
747	}
748	return result, off, nil
749}
750
751func unpackDataAplPrefix(msg []byte, off int) (APLPrefix, int, error) {
752	family, off, err := unpackUint16(msg, off)
753	if err != nil {
754		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"}
755	}
756	prefix, off, err := unpackUint8(msg, off)
757	if err != nil {
758		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"}
759	}
760	nlen, off, err := unpackUint8(msg, off)
761	if err != nil {
762		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"}
763	}
764
765	var ip []byte
766	switch family {
767	case 1:
768		ip = make([]byte, net.IPv4len)
769	case 2:
770		ip = make([]byte, net.IPv6len)
771	default:
772		return APLPrefix{}, len(msg), &Error{err: "unrecognized APL address family"}
773	}
774	if int(prefix) > 8*len(ip) {
775		return APLPrefix{}, len(msg), &Error{err: "APL prefix too long"}
776	}
777	afdlen := int(nlen & 0x7f)
778	if afdlen > len(ip) {
779		return APLPrefix{}, len(msg), &Error{err: "APL length too long"}
780	}
781	if off+afdlen > len(msg) {
782		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL address"}
783	}
784	off += copy(ip, msg[off:off+afdlen])
785	if afdlen > 0 {
786		last := ip[afdlen-1]
787		if last == 0 {
788			return APLPrefix{}, len(msg), &Error{err: "extra APL address bits"}
789		}
790	}
791	ipnet := net.IPNet{
792		IP:   ip,
793		Mask: net.CIDRMask(int(prefix), 8*len(ip)),
794	}
795	network := ipnet.IP.Mask(ipnet.Mask)
796	if !network.Equal(ipnet.IP) {
797		return APLPrefix{}, len(msg), &Error{err: "invalid APL address length"}
798	}
799
800	return APLPrefix{
801		Negation: (nlen & 0x80) != 0,
802		Network:  ipnet,
803	}, off, nil
804}
805