1
2
3
4
5
6
7
8
9
10
11
12
13 package dnsmessage
14
15 import (
16 "errors"
17 )
18
19
20
21
22 type Type uint16
23
24 const (
25
26 TypeA Type = 1
27 TypeNS Type = 2
28 TypeCNAME Type = 5
29 TypeSOA Type = 6
30 TypePTR Type = 12
31 TypeMX Type = 15
32 TypeTXT Type = 16
33 TypeAAAA Type = 28
34 TypeSRV Type = 33
35 TypeOPT Type = 41
36
37
38 TypeWKS Type = 11
39 TypeHINFO Type = 13
40 TypeMINFO Type = 14
41 TypeAXFR Type = 252
42 TypeALL Type = 255
43 )
44
45 var typeNames = map[Type]string{
46 TypeA: "TypeA",
47 TypeNS: "TypeNS",
48 TypeCNAME: "TypeCNAME",
49 TypeSOA: "TypeSOA",
50 TypePTR: "TypePTR",
51 TypeMX: "TypeMX",
52 TypeTXT: "TypeTXT",
53 TypeAAAA: "TypeAAAA",
54 TypeSRV: "TypeSRV",
55 TypeOPT: "TypeOPT",
56 TypeWKS: "TypeWKS",
57 TypeHINFO: "TypeHINFO",
58 TypeMINFO: "TypeMINFO",
59 TypeAXFR: "TypeAXFR",
60 TypeALL: "TypeALL",
61 }
62
63
64 func (t Type) String() string {
65 if n, ok := typeNames[t]; ok {
66 return n
67 }
68 return printUint16(uint16(t))
69 }
70
71
72 func (t Type) GoString() string {
73 if n, ok := typeNames[t]; ok {
74 return "dnsmessage." + n
75 }
76 return printUint16(uint16(t))
77 }
78
79
80 type Class uint16
81
82 const (
83
84 ClassINET Class = 1
85 ClassCSNET Class = 2
86 ClassCHAOS Class = 3
87 ClassHESIOD Class = 4
88
89
90 ClassANY Class = 255
91 )
92
93 var classNames = map[Class]string{
94 ClassINET: "ClassINET",
95 ClassCSNET: "ClassCSNET",
96 ClassCHAOS: "ClassCHAOS",
97 ClassHESIOD: "ClassHESIOD",
98 ClassANY: "ClassANY",
99 }
100
101
102 func (c Class) String() string {
103 if n, ok := classNames[c]; ok {
104 return n
105 }
106 return printUint16(uint16(c))
107 }
108
109
110 func (c Class) GoString() string {
111 if n, ok := classNames[c]; ok {
112 return "dnsmessage." + n
113 }
114 return printUint16(uint16(c))
115 }
116
117
118 type OpCode uint16
119
120
121 func (o OpCode) GoString() string {
122 return printUint16(uint16(o))
123 }
124
125
126 type RCode uint16
127
128
129 const (
130 RCodeSuccess RCode = 0
131 RCodeFormatError RCode = 1
132 RCodeServerFailure RCode = 2
133 RCodeNameError RCode = 3
134 RCodeNotImplemented RCode = 4
135 RCodeRefused RCode = 5
136 )
137
138 var rCodeNames = map[RCode]string{
139 RCodeSuccess: "RCodeSuccess",
140 RCodeFormatError: "RCodeFormatError",
141 RCodeServerFailure: "RCodeServerFailure",
142 RCodeNameError: "RCodeNameError",
143 RCodeNotImplemented: "RCodeNotImplemented",
144 RCodeRefused: "RCodeRefused",
145 }
146
147
148 func (r RCode) String() string {
149 if n, ok := rCodeNames[r]; ok {
150 return n
151 }
152 return printUint16(uint16(r))
153 }
154
155
156 func (r RCode) GoString() string {
157 if n, ok := rCodeNames[r]; ok {
158 return "dnsmessage." + n
159 }
160 return printUint16(uint16(r))
161 }
162
163 func printPaddedUint8(i uint8) string {
164 b := byte(i)
165 return string([]byte{
166 b/100 + '0',
167 b/10%10 + '0',
168 b%10 + '0',
169 })
170 }
171
172 func printUint8Bytes(buf []byte, i uint8) []byte {
173 b := byte(i)
174 if i >= 100 {
175 buf = append(buf, b/100+'0')
176 }
177 if i >= 10 {
178 buf = append(buf, b/10%10+'0')
179 }
180 return append(buf, b%10+'0')
181 }
182
183 func printByteSlice(b []byte) string {
184 if len(b) == 0 {
185 return ""
186 }
187 buf := make([]byte, 0, 5*len(b))
188 buf = printUint8Bytes(buf, uint8(b[0]))
189 for _, n := range b[1:] {
190 buf = append(buf, ',', ' ')
191 buf = printUint8Bytes(buf, uint8(n))
192 }
193 return string(buf)
194 }
195
196 const hexDigits = "0123456789abcdef"
197
198 func printString(str []byte) string {
199 buf := make([]byte, 0, len(str))
200 for i := 0; i < len(str); i++ {
201 c := str[i]
202 if c == '.' || c == '-' || c == ' ' ||
203 'A' <= c && c <= 'Z' ||
204 'a' <= c && c <= 'z' ||
205 '0' <= c && c <= '9' {
206 buf = append(buf, c)
207 continue
208 }
209
210 upper := c >> 4
211 lower := (c << 4) >> 4
212 buf = append(
213 buf,
214 '\\',
215 'x',
216 hexDigits[upper],
217 hexDigits[lower],
218 )
219 }
220 return string(buf)
221 }
222
223 func printUint16(i uint16) string {
224 return printUint32(uint32(i))
225 }
226
227 func printUint32(i uint32) string {
228
229 buf := make([]byte, 10)
230 for b, d := buf, uint32(1000000000); d > 0; d /= 10 {
231 b[0] = byte(i/d%10 + '0')
232 if b[0] == '0' && len(b) == len(buf) && len(buf) > 1 {
233 buf = buf[1:]
234 }
235 b = b[1:]
236 i %= d
237 }
238 return string(buf)
239 }
240
241 func printBool(b bool) string {
242 if b {
243 return "true"
244 }
245 return "false"
246 }
247
248 var (
249
250
251
252 ErrNotStarted = errors.New("parsing/packing of this type isn't available yet")
253
254
255
256 ErrSectionDone = errors.New("parsing/packing of this section has completed")
257
258 errBaseLen = errors.New("insufficient data for base length type")
259 errCalcLen = errors.New("insufficient data for calculated length type")
260 errReserved = errors.New("segment prefix is reserved")
261 errTooManyPtr = errors.New("too many pointers (>10)")
262 errInvalidPtr = errors.New("invalid pointer")
263 errNilResouceBody = errors.New("nil resource body")
264 errResourceLen = errors.New("insufficient data for resource body length")
265 errSegTooLong = errors.New("segment length too long")
266 errZeroSegLen = errors.New("zero length segment")
267 errResTooLong = errors.New("resource length too long")
268 errTooManyQuestions = errors.New("too many Questions to pack (>65535)")
269 errTooManyAnswers = errors.New("too many Answers to pack (>65535)")
270 errTooManyAuthorities = errors.New("too many Authorities to pack (>65535)")
271 errTooManyAdditionals = errors.New("too many Additionals to pack (>65535)")
272 errNonCanonicalName = errors.New("name is not in canonical format (it must end with a .)")
273 errStringTooLong = errors.New("character string exceeds maximum length (255)")
274 errCompressedSRV = errors.New("compressed name in SRV resource data")
275 )
276
277
278 const (
279
280
281
282
283
284 packStartingCap = 512
285
286
287 uint16Len = 2
288
289
290 uint32Len = 4
291
292
293
294
295 headerLen = 6 * uint16Len
296 )
297
298 type nestedError struct {
299
300 s string
301
302
303 err error
304 }
305
306
307 func (e *nestedError) Error() string {
308 return e.s + ": " + e.err.Error()
309 }
310
311
312 type Header struct {
313 ID uint16
314 Response bool
315 OpCode OpCode
316 Authoritative bool
317 Truncated bool
318 RecursionDesired bool
319 RecursionAvailable bool
320 RCode RCode
321 }
322
323 func (m *Header) pack() (id uint16, bits uint16) {
324 id = m.ID
325 bits = uint16(m.OpCode)<<11 | uint16(m.RCode)
326 if m.RecursionAvailable {
327 bits |= headerBitRA
328 }
329 if m.RecursionDesired {
330 bits |= headerBitRD
331 }
332 if m.Truncated {
333 bits |= headerBitTC
334 }
335 if m.Authoritative {
336 bits |= headerBitAA
337 }
338 if m.Response {
339 bits |= headerBitQR
340 }
341 return
342 }
343
344
345 func (m *Header) GoString() string {
346 return "dnsmessage.Header{" +
347 "ID: " + printUint16(m.ID) + ", " +
348 "Response: " + printBool(m.Response) + ", " +
349 "OpCode: " + m.OpCode.GoString() + ", " +
350 "Authoritative: " + printBool(m.Authoritative) + ", " +
351 "Truncated: " + printBool(m.Truncated) + ", " +
352 "RecursionDesired: " + printBool(m.RecursionDesired) + ", " +
353 "RecursionAvailable: " + printBool(m.RecursionAvailable) + ", " +
354 "RCode: " + m.RCode.GoString() + "}"
355 }
356
357
358 type Message struct {
359 Header
360 Questions []Question
361 Answers []Resource
362 Authorities []Resource
363 Additionals []Resource
364 }
365
366 type section uint8
367
368 const (
369 sectionNotStarted section = iota
370 sectionHeader
371 sectionQuestions
372 sectionAnswers
373 sectionAuthorities
374 sectionAdditionals
375 sectionDone
376
377 headerBitQR = 1 << 15
378 headerBitAA = 1 << 10
379 headerBitTC = 1 << 9
380 headerBitRD = 1 << 8
381 headerBitRA = 1 << 7
382 )
383
384 var sectionNames = map[section]string{
385 sectionHeader: "header",
386 sectionQuestions: "Question",
387 sectionAnswers: "Answer",
388 sectionAuthorities: "Authority",
389 sectionAdditionals: "Additional",
390 }
391
392
393 type header struct {
394 id uint16
395 bits uint16
396 questions uint16
397 answers uint16
398 authorities uint16
399 additionals uint16
400 }
401
402 func (h *header) count(sec section) uint16 {
403 switch sec {
404 case sectionQuestions:
405 return h.questions
406 case sectionAnswers:
407 return h.answers
408 case sectionAuthorities:
409 return h.authorities
410 case sectionAdditionals:
411 return h.additionals
412 }
413 return 0
414 }
415
416
417 func (h *header) pack(msg []byte) []byte {
418 msg = packUint16(msg, h.id)
419 msg = packUint16(msg, h.bits)
420 msg = packUint16(msg, h.questions)
421 msg = packUint16(msg, h.answers)
422 msg = packUint16(msg, h.authorities)
423 return packUint16(msg, h.additionals)
424 }
425
426 func (h *header) unpack(msg []byte, off int) (int, error) {
427 newOff := off
428 var err error
429 if h.id, newOff, err = unpackUint16(msg, newOff); err != nil {
430 return off, &nestedError{"id", err}
431 }
432 if h.bits, newOff, err = unpackUint16(msg, newOff); err != nil {
433 return off, &nestedError{"bits", err}
434 }
435 if h.questions, newOff, err = unpackUint16(msg, newOff); err != nil {
436 return off, &nestedError{"questions", err}
437 }
438 if h.answers, newOff, err = unpackUint16(msg, newOff); err != nil {
439 return off, &nestedError{"answers", err}
440 }
441 if h.authorities, newOff, err = unpackUint16(msg, newOff); err != nil {
442 return off, &nestedError{"authorities", err}
443 }
444 if h.additionals, newOff, err = unpackUint16(msg, newOff); err != nil {
445 return off, &nestedError{"additionals", err}
446 }
447 return newOff, nil
448 }
449
450 func (h *header) header() Header {
451 return Header{
452 ID: h.id,
453 Response: (h.bits & headerBitQR) != 0,
454 OpCode: OpCode(h.bits>>11) & 0xF,
455 Authoritative: (h.bits & headerBitAA) != 0,
456 Truncated: (h.bits & headerBitTC) != 0,
457 RecursionDesired: (h.bits & headerBitRD) != 0,
458 RecursionAvailable: (h.bits & headerBitRA) != 0,
459 RCode: RCode(h.bits & 0xF),
460 }
461 }
462
463
464 type Resource struct {
465 Header ResourceHeader
466 Body ResourceBody
467 }
468
469 func (r *Resource) GoString() string {
470 return "dnsmessage.Resource{" +
471 "Header: " + r.Header.GoString() +
472 ", Body: &" + r.Body.GoString() +
473 "}"
474 }
475
476
477 type ResourceBody interface {
478
479 pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error)
480
481
482
483 realType() Type
484
485
486 GoString() string
487 }
488
489
490 func (r *Resource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
491 if r.Body == nil {
492 return msg, errNilResouceBody
493 }
494 oldMsg := msg
495 r.Header.Type = r.Body.realType()
496 msg, lenOff, err := r.Header.pack(msg, compression, compressionOff)
497 if err != nil {
498 return msg, &nestedError{"ResourceHeader", err}
499 }
500 preLen := len(msg)
501 msg, err = r.Body.pack(msg, compression, compressionOff)
502 if err != nil {
503 return msg, &nestedError{"content", err}
504 }
505 if err := r.Header.fixLen(msg, lenOff, preLen); err != nil {
506 return oldMsg, err
507 }
508 return msg, nil
509 }
510
511
512
513
514
515
516
517
518
519
520
521
522
523 type Parser struct {
524 msg []byte
525 header header
526
527 section section
528 off int
529 index int
530 resHeaderValid bool
531 resHeader ResourceHeader
532 }
533
534
535 func (p *Parser) Start(msg []byte) (Header, error) {
536 if p.msg != nil {
537 *p = Parser{}
538 }
539 p.msg = msg
540 var err error
541 if p.off, err = p.header.unpack(msg, 0); err != nil {
542 return Header{}, &nestedError{"unpacking header", err}
543 }
544 p.section = sectionQuestions
545 return p.header.header(), nil
546 }
547
548 func (p *Parser) checkAdvance(sec section) error {
549 if p.section < sec {
550 return ErrNotStarted
551 }
552 if p.section > sec {
553 return ErrSectionDone
554 }
555 p.resHeaderValid = false
556 if p.index == int(p.header.count(sec)) {
557 p.index = 0
558 p.section++
559 return ErrSectionDone
560 }
561 return nil
562 }
563
564 func (p *Parser) resource(sec section) (Resource, error) {
565 var r Resource
566 var err error
567 r.Header, err = p.resourceHeader(sec)
568 if err != nil {
569 return r, err
570 }
571 p.resHeaderValid = false
572 r.Body, p.off, err = unpackResourceBody(p.msg, p.off, r.Header)
573 if err != nil {
574 return Resource{}, &nestedError{"unpacking " + sectionNames[sec], err}
575 }
576 p.index++
577 return r, nil
578 }
579
580 func (p *Parser) resourceHeader(sec section) (ResourceHeader, error) {
581 if p.resHeaderValid {
582 return p.resHeader, nil
583 }
584 if err := p.checkAdvance(sec); err != nil {
585 return ResourceHeader{}, err
586 }
587 var hdr ResourceHeader
588 off, err := hdr.unpack(p.msg, p.off)
589 if err != nil {
590 return ResourceHeader{}, err
591 }
592 p.resHeaderValid = true
593 p.resHeader = hdr
594 p.off = off
595 return hdr, nil
596 }
597
598 func (p *Parser) skipResource(sec section) error {
599 if p.resHeaderValid {
600 newOff := p.off + int(p.resHeader.Length)
601 if newOff > len(p.msg) {
602 return errResourceLen
603 }
604 p.off = newOff
605 p.resHeaderValid = false
606 p.index++
607 return nil
608 }
609 if err := p.checkAdvance(sec); err != nil {
610 return err
611 }
612 var err error
613 p.off, err = skipResource(p.msg, p.off)
614 if err != nil {
615 return &nestedError{"skipping: " + sectionNames[sec], err}
616 }
617 p.index++
618 return nil
619 }
620
621
622 func (p *Parser) Question() (Question, error) {
623 if err := p.checkAdvance(sectionQuestions); err != nil {
624 return Question{}, err
625 }
626 var name Name
627 off, err := name.unpack(p.msg, p.off)
628 if err != nil {
629 return Question{}, &nestedError{"unpacking Question.Name", err}
630 }
631 typ, off, err := unpackType(p.msg, off)
632 if err != nil {
633 return Question{}, &nestedError{"unpacking Question.Type", err}
634 }
635 class, off, err := unpackClass(p.msg, off)
636 if err != nil {
637 return Question{}, &nestedError{"unpacking Question.Class", err}
638 }
639 p.off = off
640 p.index++
641 return Question{name, typ, class}, nil
642 }
643
644
645 func (p *Parser) AllQuestions() ([]Question, error) {
646
647
648
649
650
651
652 qs := []Question{}
653 for {
654 q, err := p.Question()
655 if err == ErrSectionDone {
656 return qs, nil
657 }
658 if err != nil {
659 return nil, err
660 }
661 qs = append(qs, q)
662 }
663 }
664
665
666 func (p *Parser) SkipQuestion() error {
667 if err := p.checkAdvance(sectionQuestions); err != nil {
668 return err
669 }
670 off, err := skipName(p.msg, p.off)
671 if err != nil {
672 return &nestedError{"skipping Question Name", err}
673 }
674 if off, err = skipType(p.msg, off); err != nil {
675 return &nestedError{"skipping Question Type", err}
676 }
677 if off, err = skipClass(p.msg, off); err != nil {
678 return &nestedError{"skipping Question Class", err}
679 }
680 p.off = off
681 p.index++
682 return nil
683 }
684
685
686 func (p *Parser) SkipAllQuestions() error {
687 for {
688 if err := p.SkipQuestion(); err == ErrSectionDone {
689 return nil
690 } else if err != nil {
691 return err
692 }
693 }
694 }
695
696
697 func (p *Parser) AnswerHeader() (ResourceHeader, error) {
698 return p.resourceHeader(sectionAnswers)
699 }
700
701
702 func (p *Parser) Answer() (Resource, error) {
703 return p.resource(sectionAnswers)
704 }
705
706
707 func (p *Parser) AllAnswers() ([]Resource, error) {
708
709
710
711
712
713 n := int(p.header.answers)
714 if n > 20 {
715 n = 20
716 }
717 as := make([]Resource, 0, n)
718 for {
719 a, err := p.Answer()
720 if err == ErrSectionDone {
721 return as, nil
722 }
723 if err != nil {
724 return nil, err
725 }
726 as = append(as, a)
727 }
728 }
729
730
731 func (p *Parser) SkipAnswer() error {
732 return p.skipResource(sectionAnswers)
733 }
734
735
736 func (p *Parser) SkipAllAnswers() error {
737 for {
738 if err := p.SkipAnswer(); err == ErrSectionDone {
739 return nil
740 } else if err != nil {
741 return err
742 }
743 }
744 }
745
746
747 func (p *Parser) AuthorityHeader() (ResourceHeader, error) {
748 return p.resourceHeader(sectionAuthorities)
749 }
750
751
752 func (p *Parser) Authority() (Resource, error) {
753 return p.resource(sectionAuthorities)
754 }
755
756
757 func (p *Parser) AllAuthorities() ([]Resource, error) {
758
759
760
761
762
763 n := int(p.header.authorities)
764 if n > 10 {
765 n = 10
766 }
767 as := make([]Resource, 0, n)
768 for {
769 a, err := p.Authority()
770 if err == ErrSectionDone {
771 return as, nil
772 }
773 if err != nil {
774 return nil, err
775 }
776 as = append(as, a)
777 }
778 }
779
780
781 func (p *Parser) SkipAuthority() error {
782 return p.skipResource(sectionAuthorities)
783 }
784
785
786 func (p *Parser) SkipAllAuthorities() error {
787 for {
788 if err := p.SkipAuthority(); err == ErrSectionDone {
789 return nil
790 } else if err != nil {
791 return err
792 }
793 }
794 }
795
796
797 func (p *Parser) AdditionalHeader() (ResourceHeader, error) {
798 return p.resourceHeader(sectionAdditionals)
799 }
800
801
802 func (p *Parser) Additional() (Resource, error) {
803 return p.resource(sectionAdditionals)
804 }
805
806
807 func (p *Parser) AllAdditionals() ([]Resource, error) {
808
809
810
811
812
813 n := int(p.header.additionals)
814 if n > 10 {
815 n = 10
816 }
817 as := make([]Resource, 0, n)
818 for {
819 a, err := p.Additional()
820 if err == ErrSectionDone {
821 return as, nil
822 }
823 if err != nil {
824 return nil, err
825 }
826 as = append(as, a)
827 }
828 }
829
830
831 func (p *Parser) SkipAdditional() error {
832 return p.skipResource(sectionAdditionals)
833 }
834
835
836 func (p *Parser) SkipAllAdditionals() error {
837 for {
838 if err := p.SkipAdditional(); err == ErrSectionDone {
839 return nil
840 } else if err != nil {
841 return err
842 }
843 }
844 }
845
846
847
848
849
850 func (p *Parser) CNAMEResource() (CNAMEResource, error) {
851 if !p.resHeaderValid || p.resHeader.Type != TypeCNAME {
852 return CNAMEResource{}, ErrNotStarted
853 }
854 r, err := unpackCNAMEResource(p.msg, p.off)
855 if err != nil {
856 return CNAMEResource{}, err
857 }
858 p.off += int(p.resHeader.Length)
859 p.resHeaderValid = false
860 p.index++
861 return r, nil
862 }
863
864
865
866
867
868 func (p *Parser) MXResource() (MXResource, error) {
869 if !p.resHeaderValid || p.resHeader.Type != TypeMX {
870 return MXResource{}, ErrNotStarted
871 }
872 r, err := unpackMXResource(p.msg, p.off)
873 if err != nil {
874 return MXResource{}, err
875 }
876 p.off += int(p.resHeader.Length)
877 p.resHeaderValid = false
878 p.index++
879 return r, nil
880 }
881
882
883
884
885
886 func (p *Parser) NSResource() (NSResource, error) {
887 if !p.resHeaderValid || p.resHeader.Type != TypeNS {
888 return NSResource{}, ErrNotStarted
889 }
890 r, err := unpackNSResource(p.msg, p.off)
891 if err != nil {
892 return NSResource{}, err
893 }
894 p.off += int(p.resHeader.Length)
895 p.resHeaderValid = false
896 p.index++
897 return r, nil
898 }
899
900
901
902
903
904 func (p *Parser) PTRResource() (PTRResource, error) {
905 if !p.resHeaderValid || p.resHeader.Type != TypePTR {
906 return PTRResource{}, ErrNotStarted
907 }
908 r, err := unpackPTRResource(p.msg, p.off)
909 if err != nil {
910 return PTRResource{}, err
911 }
912 p.off += int(p.resHeader.Length)
913 p.resHeaderValid = false
914 p.index++
915 return r, nil
916 }
917
918
919
920
921
922 func (p *Parser) SOAResource() (SOAResource, error) {
923 if !p.resHeaderValid || p.resHeader.Type != TypeSOA {
924 return SOAResource{}, ErrNotStarted
925 }
926 r, err := unpackSOAResource(p.msg, p.off)
927 if err != nil {
928 return SOAResource{}, err
929 }
930 p.off += int(p.resHeader.Length)
931 p.resHeaderValid = false
932 p.index++
933 return r, nil
934 }
935
936
937
938
939
940 func (p *Parser) TXTResource() (TXTResource, error) {
941 if !p.resHeaderValid || p.resHeader.Type != TypeTXT {
942 return TXTResource{}, ErrNotStarted
943 }
944 r, err := unpackTXTResource(p.msg, p.off, p.resHeader.Length)
945 if err != nil {
946 return TXTResource{}, err
947 }
948 p.off += int(p.resHeader.Length)
949 p.resHeaderValid = false
950 p.index++
951 return r, nil
952 }
953
954
955
956
957
958 func (p *Parser) SRVResource() (SRVResource, error) {
959 if !p.resHeaderValid || p.resHeader.Type != TypeSRV {
960 return SRVResource{}, ErrNotStarted
961 }
962 r, err := unpackSRVResource(p.msg, p.off)
963 if err != nil {
964 return SRVResource{}, err
965 }
966 p.off += int(p.resHeader.Length)
967 p.resHeaderValid = false
968 p.index++
969 return r, nil
970 }
971
972
973
974
975
976 func (p *Parser) AResource() (AResource, error) {
977 if !p.resHeaderValid || p.resHeader.Type != TypeA {
978 return AResource{}, ErrNotStarted
979 }
980 r, err := unpackAResource(p.msg, p.off)
981 if err != nil {
982 return AResource{}, err
983 }
984 p.off += int(p.resHeader.Length)
985 p.resHeaderValid = false
986 p.index++
987 return r, nil
988 }
989
990
991
992
993
994 func (p *Parser) AAAAResource() (AAAAResource, error) {
995 if !p.resHeaderValid || p.resHeader.Type != TypeAAAA {
996 return AAAAResource{}, ErrNotStarted
997 }
998 r, err := unpackAAAAResource(p.msg, p.off)
999 if err != nil {
1000 return AAAAResource{}, err
1001 }
1002 p.off += int(p.resHeader.Length)
1003 p.resHeaderValid = false
1004 p.index++
1005 return r, nil
1006 }
1007
1008
1009
1010
1011
1012 func (p *Parser) OPTResource() (OPTResource, error) {
1013 if !p.resHeaderValid || p.resHeader.Type != TypeOPT {
1014 return OPTResource{}, ErrNotStarted
1015 }
1016 r, err := unpackOPTResource(p.msg, p.off, p.resHeader.Length)
1017 if err != nil {
1018 return OPTResource{}, err
1019 }
1020 p.off += int(p.resHeader.Length)
1021 p.resHeaderValid = false
1022 p.index++
1023 return r, nil
1024 }
1025
1026
1027
1028
1029
1030 func (p *Parser) UnknownResource() (UnknownResource, error) {
1031 if !p.resHeaderValid {
1032 return UnknownResource{}, ErrNotStarted
1033 }
1034 r, err := unpackUnknownResource(p.resHeader.Type, p.msg, p.off, p.resHeader.Length)
1035 if err != nil {
1036 return UnknownResource{}, err
1037 }
1038 p.off += int(p.resHeader.Length)
1039 p.resHeaderValid = false
1040 p.index++
1041 return r, nil
1042 }
1043
1044
1045 func (m *Message) Unpack(msg []byte) error {
1046 var p Parser
1047 var err error
1048 if m.Header, err = p.Start(msg); err != nil {
1049 return err
1050 }
1051 if m.Questions, err = p.AllQuestions(); err != nil {
1052 return err
1053 }
1054 if m.Answers, err = p.AllAnswers(); err != nil {
1055 return err
1056 }
1057 if m.Authorities, err = p.AllAuthorities(); err != nil {
1058 return err
1059 }
1060 if m.Additionals, err = p.AllAdditionals(); err != nil {
1061 return err
1062 }
1063 return nil
1064 }
1065
1066
1067 func (m *Message) Pack() ([]byte, error) {
1068 return m.AppendPack(make([]byte, 0, packStartingCap))
1069 }
1070
1071
1072
1073 func (m *Message) AppendPack(b []byte) ([]byte, error) {
1074
1075
1076
1077 if len(m.Questions) > int(^uint16(0)) {
1078 return nil, errTooManyQuestions
1079 }
1080 if len(m.Answers) > int(^uint16(0)) {
1081 return nil, errTooManyAnswers
1082 }
1083 if len(m.Authorities) > int(^uint16(0)) {
1084 return nil, errTooManyAuthorities
1085 }
1086 if len(m.Additionals) > int(^uint16(0)) {
1087 return nil, errTooManyAdditionals
1088 }
1089
1090 var h header
1091 h.id, h.bits = m.Header.pack()
1092
1093 h.questions = uint16(len(m.Questions))
1094 h.answers = uint16(len(m.Answers))
1095 h.authorities = uint16(len(m.Authorities))
1096 h.additionals = uint16(len(m.Additionals))
1097
1098 compressionOff := len(b)
1099 msg := h.pack(b)
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109 compression := map[string]int{}
1110
1111 for i := range m.Questions {
1112 var err error
1113 if msg, err = m.Questions[i].pack(msg, compression, compressionOff); err != nil {
1114 return nil, &nestedError{"packing Question", err}
1115 }
1116 }
1117 for i := range m.Answers {
1118 var err error
1119 if msg, err = m.Answers[i].pack(msg, compression, compressionOff); err != nil {
1120 return nil, &nestedError{"packing Answer", err}
1121 }
1122 }
1123 for i := range m.Authorities {
1124 var err error
1125 if msg, err = m.Authorities[i].pack(msg, compression, compressionOff); err != nil {
1126 return nil, &nestedError{"packing Authority", err}
1127 }
1128 }
1129 for i := range m.Additionals {
1130 var err error
1131 if msg, err = m.Additionals[i].pack(msg, compression, compressionOff); err != nil {
1132 return nil, &nestedError{"packing Additional", err}
1133 }
1134 }
1135
1136 return msg, nil
1137 }
1138
1139
1140 func (m *Message) GoString() string {
1141 s := "dnsmessage.Message{Header: " + m.Header.GoString() + ", " +
1142 "Questions: []dnsmessage.Question{"
1143 if len(m.Questions) > 0 {
1144 s += m.Questions[0].GoString()
1145 for _, q := range m.Questions[1:] {
1146 s += ", " + q.GoString()
1147 }
1148 }
1149 s += "}, Answers: []dnsmessage.Resource{"
1150 if len(m.Answers) > 0 {
1151 s += m.Answers[0].GoString()
1152 for _, a := range m.Answers[1:] {
1153 s += ", " + a.GoString()
1154 }
1155 }
1156 s += "}, Authorities: []dnsmessage.Resource{"
1157 if len(m.Authorities) > 0 {
1158 s += m.Authorities[0].GoString()
1159 for _, a := range m.Authorities[1:] {
1160 s += ", " + a.GoString()
1161 }
1162 }
1163 s += "}, Additionals: []dnsmessage.Resource{"
1164 if len(m.Additionals) > 0 {
1165 s += m.Additionals[0].GoString()
1166 for _, a := range m.Additionals[1:] {
1167 s += ", " + a.GoString()
1168 }
1169 }
1170 return s + "}}"
1171 }
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183 type Builder struct {
1184
1185 msg []byte
1186
1187
1188 section section
1189
1190
1191
1192 header header
1193
1194
1195 start int
1196
1197
1198
1199 compression map[string]int
1200 }
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212 func NewBuilder(buf []byte, h Header) Builder {
1213 if buf == nil {
1214 buf = make([]byte, 0, packStartingCap)
1215 }
1216 b := Builder{msg: buf, start: len(buf)}
1217 b.header.id, b.header.bits = h.pack()
1218 var hb [headerLen]byte
1219 b.msg = append(b.msg, hb[:]...)
1220 b.section = sectionHeader
1221 return b
1222 }
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235 func (b *Builder) EnableCompression() {
1236 b.compression = map[string]int{}
1237 }
1238
1239 func (b *Builder) startCheck(s section) error {
1240 if b.section <= sectionNotStarted {
1241 return ErrNotStarted
1242 }
1243 if b.section > s {
1244 return ErrSectionDone
1245 }
1246 return nil
1247 }
1248
1249
1250 func (b *Builder) StartQuestions() error {
1251 if err := b.startCheck(sectionQuestions); err != nil {
1252 return err
1253 }
1254 b.section = sectionQuestions
1255 return nil
1256 }
1257
1258
1259 func (b *Builder) StartAnswers() error {
1260 if err := b.startCheck(sectionAnswers); err != nil {
1261 return err
1262 }
1263 b.section = sectionAnswers
1264 return nil
1265 }
1266
1267
1268 func (b *Builder) StartAuthorities() error {
1269 if err := b.startCheck(sectionAuthorities); err != nil {
1270 return err
1271 }
1272 b.section = sectionAuthorities
1273 return nil
1274 }
1275
1276
1277 func (b *Builder) StartAdditionals() error {
1278 if err := b.startCheck(sectionAdditionals); err != nil {
1279 return err
1280 }
1281 b.section = sectionAdditionals
1282 return nil
1283 }
1284
1285 func (b *Builder) incrementSectionCount() error {
1286 var count *uint16
1287 var err error
1288 switch b.section {
1289 case sectionQuestions:
1290 count = &b.header.questions
1291 err = errTooManyQuestions
1292 case sectionAnswers:
1293 count = &b.header.answers
1294 err = errTooManyAnswers
1295 case sectionAuthorities:
1296 count = &b.header.authorities
1297 err = errTooManyAuthorities
1298 case sectionAdditionals:
1299 count = &b.header.additionals
1300 err = errTooManyAdditionals
1301 }
1302 if *count == ^uint16(0) {
1303 return err
1304 }
1305 *count++
1306 return nil
1307 }
1308
1309
1310 func (b *Builder) Question(q Question) error {
1311 if b.section < sectionQuestions {
1312 return ErrNotStarted
1313 }
1314 if b.section > sectionQuestions {
1315 return ErrSectionDone
1316 }
1317 msg, err := q.pack(b.msg, b.compression, b.start)
1318 if err != nil {
1319 return err
1320 }
1321 if err := b.incrementSectionCount(); err != nil {
1322 return err
1323 }
1324 b.msg = msg
1325 return nil
1326 }
1327
1328 func (b *Builder) checkResourceSection() error {
1329 if b.section < sectionAnswers {
1330 return ErrNotStarted
1331 }
1332 if b.section > sectionAdditionals {
1333 return ErrSectionDone
1334 }
1335 return nil
1336 }
1337
1338
1339 func (b *Builder) CNAMEResource(h ResourceHeader, r CNAMEResource) error {
1340 if err := b.checkResourceSection(); err != nil {
1341 return err
1342 }
1343 h.Type = r.realType()
1344 msg, lenOff, err := h.pack(b.msg, b.compression, b.start)
1345 if err != nil {
1346 return &nestedError{"ResourceHeader", err}
1347 }
1348 preLen := len(msg)
1349 if msg, err = r.pack(msg, b.compression, b.start); err != nil {
1350 return &nestedError{"CNAMEResource body", err}
1351 }
1352 if err := h.fixLen(msg, lenOff, preLen); err != nil {
1353 return err
1354 }
1355 if err := b.incrementSectionCount(); err != nil {
1356 return err
1357 }
1358 b.msg = msg
1359 return nil
1360 }
1361
1362
1363 func (b *Builder) MXResource(h ResourceHeader, r MXResource) error {
1364 if err := b.checkResourceSection(); err != nil {
1365 return err
1366 }
1367 h.Type = r.realType()
1368 msg, lenOff, err := h.pack(b.msg, b.compression, b.start)
1369 if err != nil {
1370 return &nestedError{"ResourceHeader", err}
1371 }
1372 preLen := len(msg)
1373 if msg, err = r.pack(msg, b.compression, b.start); err != nil {
1374 return &nestedError{"MXResource body", err}
1375 }
1376 if err := h.fixLen(msg, lenOff, preLen); err != nil {
1377 return err
1378 }
1379 if err := b.incrementSectionCount(); err != nil {
1380 return err
1381 }
1382 b.msg = msg
1383 return nil
1384 }
1385
1386
1387 func (b *Builder) NSResource(h ResourceHeader, r NSResource) error {
1388 if err := b.checkResourceSection(); err != nil {
1389 return err
1390 }
1391 h.Type = r.realType()
1392 msg, lenOff, err := h.pack(b.msg, b.compression, b.start)
1393 if err != nil {
1394 return &nestedError{"ResourceHeader", err}
1395 }
1396 preLen := len(msg)
1397 if msg, err = r.pack(msg, b.compression, b.start); err != nil {
1398 return &nestedError{"NSResource body", err}
1399 }
1400 if err := h.fixLen(msg, lenOff, preLen); err != nil {
1401 return err
1402 }
1403 if err := b.incrementSectionCount(); err != nil {
1404 return err
1405 }
1406 b.msg = msg
1407 return nil
1408 }
1409
1410
1411 func (b *Builder) PTRResource(h ResourceHeader, r PTRResource) error {
1412 if err := b.checkResourceSection(); err != nil {
1413 return err
1414 }
1415 h.Type = r.realType()
1416 msg, lenOff, err := h.pack(b.msg, b.compression, b.start)
1417 if err != nil {
1418 return &nestedError{"ResourceHeader", err}
1419 }
1420 preLen := len(msg)
1421 if msg, err = r.pack(msg, b.compression, b.start); err != nil {
1422 return &nestedError{"PTRResource body", err}
1423 }
1424 if err := h.fixLen(msg, lenOff, preLen); err != nil {
1425 return err
1426 }
1427 if err := b.incrementSectionCount(); err != nil {
1428 return err
1429 }
1430 b.msg = msg
1431 return nil
1432 }
1433
1434
1435 func (b *Builder) SOAResource(h ResourceHeader, r SOAResource) error {
1436 if err := b.checkResourceSection(); err != nil {
1437 return err
1438 }
1439 h.Type = r.realType()
1440 msg, lenOff, err := h.pack(b.msg, b.compression, b.start)
1441 if err != nil {
1442 return &nestedError{"ResourceHeader", err}
1443 }
1444 preLen := len(msg)
1445 if msg, err = r.pack(msg, b.compression, b.start); err != nil {
1446 return &nestedError{"SOAResource body", err}
1447 }
1448 if err := h.fixLen(msg, lenOff, preLen); err != nil {
1449 return err
1450 }
1451 if err := b.incrementSectionCount(); err != nil {
1452 return err
1453 }
1454 b.msg = msg
1455 return nil
1456 }
1457
1458
1459 func (b *Builder) TXTResource(h ResourceHeader, r TXTResource) error {
1460 if err := b.checkResourceSection(); err != nil {
1461 return err
1462 }
1463 h.Type = r.realType()
1464 msg, lenOff, err := h.pack(b.msg, b.compression, b.start)
1465 if err != nil {
1466 return &nestedError{"ResourceHeader", err}
1467 }
1468 preLen := len(msg)
1469 if msg, err = r.pack(msg, b.compression, b.start); err != nil {
1470 return &nestedError{"TXTResource body", err}
1471 }
1472 if err := h.fixLen(msg, lenOff, preLen); err != nil {
1473 return err
1474 }
1475 if err := b.incrementSectionCount(); err != nil {
1476 return err
1477 }
1478 b.msg = msg
1479 return nil
1480 }
1481
1482
1483 func (b *Builder) SRVResource(h ResourceHeader, r SRVResource) error {
1484 if err := b.checkResourceSection(); err != nil {
1485 return err
1486 }
1487 h.Type = r.realType()
1488 msg, lenOff, err := h.pack(b.msg, b.compression, b.start)
1489 if err != nil {
1490 return &nestedError{"ResourceHeader", err}
1491 }
1492 preLen := len(msg)
1493 if msg, err = r.pack(msg, b.compression, b.start); err != nil {
1494 return &nestedError{"SRVResource body", err}
1495 }
1496 if err := h.fixLen(msg, lenOff, preLen); err != nil {
1497 return err
1498 }
1499 if err := b.incrementSectionCount(); err != nil {
1500 return err
1501 }
1502 b.msg = msg
1503 return nil
1504 }
1505
1506
1507 func (b *Builder) AResource(h ResourceHeader, r AResource) error {
1508 if err := b.checkResourceSection(); err != nil {
1509 return err
1510 }
1511 h.Type = r.realType()
1512 msg, lenOff, err := h.pack(b.msg, b.compression, b.start)
1513 if err != nil {
1514 return &nestedError{"ResourceHeader", err}
1515 }
1516 preLen := len(msg)
1517 if msg, err = r.pack(msg, b.compression, b.start); err != nil {
1518 return &nestedError{"AResource body", err}
1519 }
1520 if err := h.fixLen(msg, lenOff, preLen); err != nil {
1521 return err
1522 }
1523 if err := b.incrementSectionCount(); err != nil {
1524 return err
1525 }
1526 b.msg = msg
1527 return nil
1528 }
1529
1530
1531 func (b *Builder) AAAAResource(h ResourceHeader, r AAAAResource) error {
1532 if err := b.checkResourceSection(); err != nil {
1533 return err
1534 }
1535 h.Type = r.realType()
1536 msg, lenOff, err := h.pack(b.msg, b.compression, b.start)
1537 if err != nil {
1538 return &nestedError{"ResourceHeader", err}
1539 }
1540 preLen := len(msg)
1541 if msg, err = r.pack(msg, b.compression, b.start); err != nil {
1542 return &nestedError{"AAAAResource body", err}
1543 }
1544 if err := h.fixLen(msg, lenOff, preLen); err != nil {
1545 return err
1546 }
1547 if err := b.incrementSectionCount(); err != nil {
1548 return err
1549 }
1550 b.msg = msg
1551 return nil
1552 }
1553
1554
1555 func (b *Builder) OPTResource(h ResourceHeader, r OPTResource) error {
1556 if err := b.checkResourceSection(); err != nil {
1557 return err
1558 }
1559 h.Type = r.realType()
1560 msg, lenOff, err := h.pack(b.msg, b.compression, b.start)
1561 if err != nil {
1562 return &nestedError{"ResourceHeader", err}
1563 }
1564 preLen := len(msg)
1565 if msg, err = r.pack(msg, b.compression, b.start); err != nil {
1566 return &nestedError{"OPTResource body", err}
1567 }
1568 if err := h.fixLen(msg, lenOff, preLen); err != nil {
1569 return err
1570 }
1571 if err := b.incrementSectionCount(); err != nil {
1572 return err
1573 }
1574 b.msg = msg
1575 return nil
1576 }
1577
1578
1579 func (b *Builder) UnknownResource(h ResourceHeader, r UnknownResource) error {
1580 if err := b.checkResourceSection(); err != nil {
1581 return err
1582 }
1583 h.Type = r.realType()
1584 msg, lenOff, err := h.pack(b.msg, b.compression, b.start)
1585 if err != nil {
1586 return &nestedError{"ResourceHeader", err}
1587 }
1588 preLen := len(msg)
1589 if msg, err = r.pack(msg, b.compression, b.start); err != nil {
1590 return &nestedError{"UnknownResource body", err}
1591 }
1592 if err := h.fixLen(msg, lenOff, preLen); err != nil {
1593 return err
1594 }
1595 if err := b.incrementSectionCount(); err != nil {
1596 return err
1597 }
1598 b.msg = msg
1599 return nil
1600 }
1601
1602
1603 func (b *Builder) Finish() ([]byte, error) {
1604 if b.section < sectionHeader {
1605 return nil, ErrNotStarted
1606 }
1607 b.section = sectionDone
1608
1609 b.header.pack(b.msg[b.start:b.start])
1610 return b.msg, nil
1611 }
1612
1613
1614
1615 type ResourceHeader struct {
1616
1617 Name Name
1618
1619
1620
1621
1622 Type Type
1623
1624
1625
1626 Class Class
1627
1628
1629
1630
1631 TTL uint32
1632
1633
1634
1635
1636 Length uint16
1637 }
1638
1639
1640 func (h *ResourceHeader) GoString() string {
1641 return "dnsmessage.ResourceHeader{" +
1642 "Name: " + h.Name.GoString() + ", " +
1643 "Type: " + h.Type.GoString() + ", " +
1644 "Class: " + h.Class.GoString() + ", " +
1645 "TTL: " + printUint32(h.TTL) + ", " +
1646 "Length: " + printUint16(h.Length) + "}"
1647 }
1648
1649
1650
1651
1652 func (h *ResourceHeader) pack(oldMsg []byte, compression map[string]int, compressionOff int) (msg []byte, lenOff int, err error) {
1653 msg = oldMsg
1654 if msg, err = h.Name.pack(msg, compression, compressionOff); err != nil {
1655 return oldMsg, 0, &nestedError{"Name", err}
1656 }
1657 msg = packType(msg, h.Type)
1658 msg = packClass(msg, h.Class)
1659 msg = packUint32(msg, h.TTL)
1660 lenOff = len(msg)
1661 msg = packUint16(msg, h.Length)
1662 return msg, lenOff, nil
1663 }
1664
1665 func (h *ResourceHeader) unpack(msg []byte, off int) (int, error) {
1666 newOff := off
1667 var err error
1668 if newOff, err = h.Name.unpack(msg, newOff); err != nil {
1669 return off, &nestedError{"Name", err}
1670 }
1671 if h.Type, newOff, err = unpackType(msg, newOff); err != nil {
1672 return off, &nestedError{"Type", err}
1673 }
1674 if h.Class, newOff, err = unpackClass(msg, newOff); err != nil {
1675 return off, &nestedError{"Class", err}
1676 }
1677 if h.TTL, newOff, err = unpackUint32(msg, newOff); err != nil {
1678 return off, &nestedError{"TTL", err}
1679 }
1680 if h.Length, newOff, err = unpackUint16(msg, newOff); err != nil {
1681 return off, &nestedError{"Length", err}
1682 }
1683 return newOff, nil
1684 }
1685
1686
1687
1688
1689
1690
1691
1692 func (h *ResourceHeader) fixLen(msg []byte, lenOff int, preLen int) error {
1693 conLen := len(msg) - preLen
1694 if conLen > int(^uint16(0)) {
1695 return errResTooLong
1696 }
1697
1698
1699 packUint16(msg[lenOff:lenOff], uint16(conLen))
1700 h.Length = uint16(conLen)
1701
1702 return nil
1703 }
1704
1705
1706 const (
1707 edns0Version = 0
1708
1709 edns0DNSSECOK = 0x00008000
1710 ednsVersionMask = 0x00ff0000
1711 edns0DNSSECOKMask = 0x00ff8000
1712 )
1713
1714
1715
1716
1717 func (h *ResourceHeader) SetEDNS0(udpPayloadLen int, extRCode RCode, dnssecOK bool) error {
1718 h.Name = Name{Data: [nameLen]byte{'.'}, Length: 1}
1719 h.Type = TypeOPT
1720 h.Class = Class(udpPayloadLen)
1721 h.TTL = uint32(extRCode) >> 4 << 24
1722 if dnssecOK {
1723 h.TTL |= edns0DNSSECOK
1724 }
1725 return nil
1726 }
1727
1728
1729 func (h *ResourceHeader) DNSSECAllowed() bool {
1730 return h.TTL&edns0DNSSECOKMask == edns0DNSSECOK
1731 }
1732
1733
1734
1735
1736 func (h *ResourceHeader) ExtendedRCode(rcode RCode) RCode {
1737 if h.TTL&ednsVersionMask == edns0Version {
1738 return RCode(h.TTL>>24<<4) | rcode
1739 }
1740 return rcode
1741 }
1742
1743 func skipResource(msg []byte, off int) (int, error) {
1744 newOff, err := skipName(msg, off)
1745 if err != nil {
1746 return off, &nestedError{"Name", err}
1747 }
1748 if newOff, err = skipType(msg, newOff); err != nil {
1749 return off, &nestedError{"Type", err}
1750 }
1751 if newOff, err = skipClass(msg, newOff); err != nil {
1752 return off, &nestedError{"Class", err}
1753 }
1754 if newOff, err = skipUint32(msg, newOff); err != nil {
1755 return off, &nestedError{"TTL", err}
1756 }
1757 length, newOff, err := unpackUint16(msg, newOff)
1758 if err != nil {
1759 return off, &nestedError{"Length", err}
1760 }
1761 if newOff += int(length); newOff > len(msg) {
1762 return off, errResourceLen
1763 }
1764 return newOff, nil
1765 }
1766
1767
1768 func packUint16(msg []byte, field uint16) []byte {
1769 return append(msg, byte(field>>8), byte(field))
1770 }
1771
1772 func unpackUint16(msg []byte, off int) (uint16, int, error) {
1773 if off+uint16Len > len(msg) {
1774 return 0, off, errBaseLen
1775 }
1776 return uint16(msg[off])<<8 | uint16(msg[off+1]), off + uint16Len, nil
1777 }
1778
1779 func skipUint16(msg []byte, off int) (int, error) {
1780 if off+uint16Len > len(msg) {
1781 return off, errBaseLen
1782 }
1783 return off + uint16Len, nil
1784 }
1785
1786
1787 func packType(msg []byte, field Type) []byte {
1788 return packUint16(msg, uint16(field))
1789 }
1790
1791 func unpackType(msg []byte, off int) (Type, int, error) {
1792 t, o, err := unpackUint16(msg, off)
1793 return Type(t), o, err
1794 }
1795
1796 func skipType(msg []byte, off int) (int, error) {
1797 return skipUint16(msg, off)
1798 }
1799
1800
1801 func packClass(msg []byte, field Class) []byte {
1802 return packUint16(msg, uint16(field))
1803 }
1804
1805 func unpackClass(msg []byte, off int) (Class, int, error) {
1806 c, o, err := unpackUint16(msg, off)
1807 return Class(c), o, err
1808 }
1809
1810 func skipClass(msg []byte, off int) (int, error) {
1811 return skipUint16(msg, off)
1812 }
1813
1814
1815 func packUint32(msg []byte, field uint32) []byte {
1816 return append(
1817 msg,
1818 byte(field>>24),
1819 byte(field>>16),
1820 byte(field>>8),
1821 byte(field),
1822 )
1823 }
1824
1825 func unpackUint32(msg []byte, off int) (uint32, int, error) {
1826 if off+uint32Len > len(msg) {
1827 return 0, off, errBaseLen
1828 }
1829 v := uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | uint32(msg[off+2])<<8 | uint32(msg[off+3])
1830 return v, off + uint32Len, nil
1831 }
1832
1833 func skipUint32(msg []byte, off int) (int, error) {
1834 if off+uint32Len > len(msg) {
1835 return off, errBaseLen
1836 }
1837 return off + uint32Len, nil
1838 }
1839
1840
1841 func packText(msg []byte, field string) ([]byte, error) {
1842 l := len(field)
1843 if l > 255 {
1844 return nil, errStringTooLong
1845 }
1846 msg = append(msg, byte(l))
1847 msg = append(msg, field...)
1848
1849 return msg, nil
1850 }
1851
1852 func unpackText(msg []byte, off int) (string, int, error) {
1853 if off >= len(msg) {
1854 return "", off, errBaseLen
1855 }
1856 beginOff := off + 1
1857 endOff := beginOff + int(msg[off])
1858 if endOff > len(msg) {
1859 return "", off, errCalcLen
1860 }
1861 return string(msg[beginOff:endOff]), endOff, nil
1862 }
1863
1864
1865 func packBytes(msg []byte, field []byte) []byte {
1866 return append(msg, field...)
1867 }
1868
1869 func unpackBytes(msg []byte, off int, field []byte) (int, error) {
1870 newOff := off + len(field)
1871 if newOff > len(msg) {
1872 return off, errBaseLen
1873 }
1874 copy(field, msg[off:newOff])
1875 return newOff, nil
1876 }
1877
1878 const nameLen = 255
1879
1880
1881
1882 type Name struct {
1883 Data [nameLen]byte
1884 Length uint8
1885 }
1886
1887
1888 func NewName(name string) (Name, error) {
1889 if len([]byte(name)) > nameLen {
1890 return Name{}, errCalcLen
1891 }
1892 n := Name{Length: uint8(len(name))}
1893 copy(n.Data[:], []byte(name))
1894 return n, nil
1895 }
1896
1897
1898 func MustNewName(name string) Name {
1899 n, err := NewName(name)
1900 if err != nil {
1901 panic("creating name: " + err.Error())
1902 }
1903 return n
1904 }
1905
1906
1907 func (n Name) String() string {
1908 return string(n.Data[:n.Length])
1909 }
1910
1911
1912 func (n *Name) GoString() string {
1913 return `dnsmessage.MustNewName("` + printString(n.Data[:n.Length]) + `")`
1914 }
1915
1916
1917
1918
1919
1920
1921
1922
1923 func (n *Name) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
1924 oldMsg := msg
1925
1926
1927 if n.Length == 0 || n.Data[n.Length-1] != '.' {
1928 return oldMsg, errNonCanonicalName
1929 }
1930
1931
1932 if n.Data[0] == '.' && n.Length == 1 {
1933 return append(msg, 0), nil
1934 }
1935
1936
1937 for i, begin := 0, 0; i < int(n.Length); i++ {
1938
1939 if n.Data[i] == '.' {
1940
1941
1942
1943 if i-begin >= 1<<6 {
1944 return oldMsg, errSegTooLong
1945 }
1946
1947
1948 if i-begin == 0 {
1949 return oldMsg, errZeroSegLen
1950 }
1951
1952 msg = append(msg, byte(i-begin))
1953
1954 for j := begin; j < i; j++ {
1955 msg = append(msg, n.Data[j])
1956 }
1957
1958 begin = i + 1
1959 continue
1960 }
1961
1962
1963
1964
1965 if (i == 0 || n.Data[i-1] == '.') && compression != nil {
1966 if ptr, ok := compression[string(n.Data[i:])]; ok {
1967
1968
1969 return append(msg, byte(ptr>>8|0xC0), byte(ptr)), nil
1970 }
1971
1972
1973
1974 if len(msg) <= int(^uint16(0)>>2) {
1975 compression[string(n.Data[i:])] = len(msg) - compressionOff
1976 }
1977 }
1978 }
1979 return append(msg, 0), nil
1980 }
1981
1982
1983 func (n *Name) unpack(msg []byte, off int) (int, error) {
1984 return n.unpackCompressed(msg, off, true )
1985 }
1986
1987 func (n *Name) unpackCompressed(msg []byte, off int, allowCompression bool) (int, error) {
1988
1989 currOff := off
1990
1991
1992
1993
1994 newOff := off
1995
1996
1997 var ptr int
1998
1999
2000 name := n.Data[:0]
2001
2002 Loop:
2003 for {
2004 if currOff >= len(msg) {
2005 return off, errBaseLen
2006 }
2007 c := int(msg[currOff])
2008 currOff++
2009 switch c & 0xC0 {
2010 case 0x00:
2011 if c == 0x00 {
2012
2013 break Loop
2014 }
2015 endOff := currOff + c
2016 if endOff > len(msg) {
2017 return off, errCalcLen
2018 }
2019 name = append(name, msg[currOff:endOff]...)
2020 name = append(name, '.')
2021 currOff = endOff
2022 case 0xC0:
2023 if !allowCompression {
2024 return off, errCompressedSRV
2025 }
2026 if currOff >= len(msg) {
2027 return off, errInvalidPtr
2028 }
2029 c1 := msg[currOff]
2030 currOff++
2031 if ptr == 0 {
2032 newOff = currOff
2033 }
2034
2035 if ptr++; ptr > 10 {
2036 return off, errTooManyPtr
2037 }
2038 currOff = (c^0xC0)<<8 | int(c1)
2039 default:
2040
2041 return off, errReserved
2042 }
2043 }
2044 if len(name) == 0 {
2045 name = append(name, '.')
2046 }
2047 if len(name) > len(n.Data) {
2048 return off, errCalcLen
2049 }
2050 n.Length = uint8(len(name))
2051 if ptr == 0 {
2052 newOff = currOff
2053 }
2054 return newOff, nil
2055 }
2056
2057 func skipName(msg []byte, off int) (int, error) {
2058
2059
2060
2061 newOff := off
2062
2063 Loop:
2064 for {
2065 if newOff >= len(msg) {
2066 return off, errBaseLen
2067 }
2068 c := int(msg[newOff])
2069 newOff++
2070 switch c & 0xC0 {
2071 case 0x00:
2072 if c == 0x00 {
2073
2074 break Loop
2075 }
2076
2077 newOff += c
2078 if newOff > len(msg) {
2079 return off, errCalcLen
2080 }
2081 case 0xC0:
2082
2083
2084
2085 newOff++
2086
2087
2088 break Loop
2089 default:
2090
2091 return off, errReserved
2092 }
2093 }
2094
2095 return newOff, nil
2096 }
2097
2098
2099 type Question struct {
2100 Name Name
2101 Type Type
2102 Class Class
2103 }
2104
2105
2106 func (q *Question) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
2107 msg, err := q.Name.pack(msg, compression, compressionOff)
2108 if err != nil {
2109 return msg, &nestedError{"Name", err}
2110 }
2111 msg = packType(msg, q.Type)
2112 return packClass(msg, q.Class), nil
2113 }
2114
2115
2116 func (q *Question) GoString() string {
2117 return "dnsmessage.Question{" +
2118 "Name: " + q.Name.GoString() + ", " +
2119 "Type: " + q.Type.GoString() + ", " +
2120 "Class: " + q.Class.GoString() + "}"
2121 }
2122
2123 func unpackResourceBody(msg []byte, off int, hdr ResourceHeader) (ResourceBody, int, error) {
2124 var (
2125 r ResourceBody
2126 err error
2127 name string
2128 )
2129 switch hdr.Type {
2130 case TypeA:
2131 var rb AResource
2132 rb, err = unpackAResource(msg, off)
2133 r = &rb
2134 name = "A"
2135 case TypeNS:
2136 var rb NSResource
2137 rb, err = unpackNSResource(msg, off)
2138 r = &rb
2139 name = "NS"
2140 case TypeCNAME:
2141 var rb CNAMEResource
2142 rb, err = unpackCNAMEResource(msg, off)
2143 r = &rb
2144 name = "CNAME"
2145 case TypeSOA:
2146 var rb SOAResource
2147 rb, err = unpackSOAResource(msg, off)
2148 r = &rb
2149 name = "SOA"
2150 case TypePTR:
2151 var rb PTRResource
2152 rb, err = unpackPTRResource(msg, off)
2153 r = &rb
2154 name = "PTR"
2155 case TypeMX:
2156 var rb MXResource
2157 rb, err = unpackMXResource(msg, off)
2158 r = &rb
2159 name = "MX"
2160 case TypeTXT:
2161 var rb TXTResource
2162 rb, err = unpackTXTResource(msg, off, hdr.Length)
2163 r = &rb
2164 name = "TXT"
2165 case TypeAAAA:
2166 var rb AAAAResource
2167 rb, err = unpackAAAAResource(msg, off)
2168 r = &rb
2169 name = "AAAA"
2170 case TypeSRV:
2171 var rb SRVResource
2172 rb, err = unpackSRVResource(msg, off)
2173 r = &rb
2174 name = "SRV"
2175 case TypeOPT:
2176 var rb OPTResource
2177 rb, err = unpackOPTResource(msg, off, hdr.Length)
2178 r = &rb
2179 name = "OPT"
2180 default:
2181 var rb UnknownResource
2182 rb, err = unpackUnknownResource(hdr.Type, msg, off, hdr.Length)
2183 r = &rb
2184 name = "Unknown"
2185 }
2186 if err != nil {
2187 return nil, off, &nestedError{name + " record", err}
2188 }
2189 return r, off + int(hdr.Length), nil
2190 }
2191
2192
2193 type CNAMEResource struct {
2194 CNAME Name
2195 }
2196
2197 func (r *CNAMEResource) realType() Type {
2198 return TypeCNAME
2199 }
2200
2201
2202 func (r *CNAMEResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
2203 return r.CNAME.pack(msg, compression, compressionOff)
2204 }
2205
2206
2207 func (r *CNAMEResource) GoString() string {
2208 return "dnsmessage.CNAMEResource{CNAME: " + r.CNAME.GoString() + "}"
2209 }
2210
2211 func unpackCNAMEResource(msg []byte, off int) (CNAMEResource, error) {
2212 var cname Name
2213 if _, err := cname.unpack(msg, off); err != nil {
2214 return CNAMEResource{}, err
2215 }
2216 return CNAMEResource{cname}, nil
2217 }
2218
2219
2220 type MXResource struct {
2221 Pref uint16
2222 MX Name
2223 }
2224
2225 func (r *MXResource) realType() Type {
2226 return TypeMX
2227 }
2228
2229
2230 func (r *MXResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
2231 oldMsg := msg
2232 msg = packUint16(msg, r.Pref)
2233 msg, err := r.MX.pack(msg, compression, compressionOff)
2234 if err != nil {
2235 return oldMsg, &nestedError{"MXResource.MX", err}
2236 }
2237 return msg, nil
2238 }
2239
2240
2241 func (r *MXResource) GoString() string {
2242 return "dnsmessage.MXResource{" +
2243 "Pref: " + printUint16(r.Pref) + ", " +
2244 "MX: " + r.MX.GoString() + "}"
2245 }
2246
2247 func unpackMXResource(msg []byte, off int) (MXResource, error) {
2248 pref, off, err := unpackUint16(msg, off)
2249 if err != nil {
2250 return MXResource{}, &nestedError{"Pref", err}
2251 }
2252 var mx Name
2253 if _, err := mx.unpack(msg, off); err != nil {
2254 return MXResource{}, &nestedError{"MX", err}
2255 }
2256 return MXResource{pref, mx}, nil
2257 }
2258
2259
2260 type NSResource struct {
2261 NS Name
2262 }
2263
2264 func (r *NSResource) realType() Type {
2265 return TypeNS
2266 }
2267
2268
2269 func (r *NSResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
2270 return r.NS.pack(msg, compression, compressionOff)
2271 }
2272
2273
2274 func (r *NSResource) GoString() string {
2275 return "dnsmessage.NSResource{NS: " + r.NS.GoString() + "}"
2276 }
2277
2278 func unpackNSResource(msg []byte, off int) (NSResource, error) {
2279 var ns Name
2280 if _, err := ns.unpack(msg, off); err != nil {
2281 return NSResource{}, err
2282 }
2283 return NSResource{ns}, nil
2284 }
2285
2286
2287 type PTRResource struct {
2288 PTR Name
2289 }
2290
2291 func (r *PTRResource) realType() Type {
2292 return TypePTR
2293 }
2294
2295
2296 func (r *PTRResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
2297 return r.PTR.pack(msg, compression, compressionOff)
2298 }
2299
2300
2301 func (r *PTRResource) GoString() string {
2302 return "dnsmessage.PTRResource{PTR: " + r.PTR.GoString() + "}"
2303 }
2304
2305 func unpackPTRResource(msg []byte, off int) (PTRResource, error) {
2306 var ptr Name
2307 if _, err := ptr.unpack(msg, off); err != nil {
2308 return PTRResource{}, err
2309 }
2310 return PTRResource{ptr}, nil
2311 }
2312
2313
2314 type SOAResource struct {
2315 NS Name
2316 MBox Name
2317 Serial uint32
2318 Refresh uint32
2319 Retry uint32
2320 Expire uint32
2321
2322
2323
2324
2325 MinTTL uint32
2326 }
2327
2328 func (r *SOAResource) realType() Type {
2329 return TypeSOA
2330 }
2331
2332
2333 func (r *SOAResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
2334 oldMsg := msg
2335 msg, err := r.NS.pack(msg, compression, compressionOff)
2336 if err != nil {
2337 return oldMsg, &nestedError{"SOAResource.NS", err}
2338 }
2339 msg, err = r.MBox.pack(msg, compression, compressionOff)
2340 if err != nil {
2341 return oldMsg, &nestedError{"SOAResource.MBox", err}
2342 }
2343 msg = packUint32(msg, r.Serial)
2344 msg = packUint32(msg, r.Refresh)
2345 msg = packUint32(msg, r.Retry)
2346 msg = packUint32(msg, r.Expire)
2347 return packUint32(msg, r.MinTTL), nil
2348 }
2349
2350
2351 func (r *SOAResource) GoString() string {
2352 return "dnsmessage.SOAResource{" +
2353 "NS: " + r.NS.GoString() + ", " +
2354 "MBox: " + r.MBox.GoString() + ", " +
2355 "Serial: " + printUint32(r.Serial) + ", " +
2356 "Refresh: " + printUint32(r.Refresh) + ", " +
2357 "Retry: " + printUint32(r.Retry) + ", " +
2358 "Expire: " + printUint32(r.Expire) + ", " +
2359 "MinTTL: " + printUint32(r.MinTTL) + "}"
2360 }
2361
2362 func unpackSOAResource(msg []byte, off int) (SOAResource, error) {
2363 var ns Name
2364 off, err := ns.unpack(msg, off)
2365 if err != nil {
2366 return SOAResource{}, &nestedError{"NS", err}
2367 }
2368 var mbox Name
2369 if off, err = mbox.unpack(msg, off); err != nil {
2370 return SOAResource{}, &nestedError{"MBox", err}
2371 }
2372 serial, off, err := unpackUint32(msg, off)
2373 if err != nil {
2374 return SOAResource{}, &nestedError{"Serial", err}
2375 }
2376 refresh, off, err := unpackUint32(msg, off)
2377 if err != nil {
2378 return SOAResource{}, &nestedError{"Refresh", err}
2379 }
2380 retry, off, err := unpackUint32(msg, off)
2381 if err != nil {
2382 return SOAResource{}, &nestedError{"Retry", err}
2383 }
2384 expire, off, err := unpackUint32(msg, off)
2385 if err != nil {
2386 return SOAResource{}, &nestedError{"Expire", err}
2387 }
2388 minTTL, _, err := unpackUint32(msg, off)
2389 if err != nil {
2390 return SOAResource{}, &nestedError{"MinTTL", err}
2391 }
2392 return SOAResource{ns, mbox, serial, refresh, retry, expire, minTTL}, nil
2393 }
2394
2395
2396 type TXTResource struct {
2397 TXT []string
2398 }
2399
2400 func (r *TXTResource) realType() Type {
2401 return TypeTXT
2402 }
2403
2404
2405 func (r *TXTResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
2406 oldMsg := msg
2407 for _, s := range r.TXT {
2408 var err error
2409 msg, err = packText(msg, s)
2410 if err != nil {
2411 return oldMsg, err
2412 }
2413 }
2414 return msg, nil
2415 }
2416
2417
2418 func (r *TXTResource) GoString() string {
2419 s := "dnsmessage.TXTResource{TXT: []string{"
2420 if len(r.TXT) == 0 {
2421 return s + "}}"
2422 }
2423 s += `"` + printString([]byte(r.TXT[0]))
2424 for _, t := range r.TXT[1:] {
2425 s += `", "` + printString([]byte(t))
2426 }
2427 return s + `"}}`
2428 }
2429
2430 func unpackTXTResource(msg []byte, off int, length uint16) (TXTResource, error) {
2431 txts := make([]string, 0, 1)
2432 for n := uint16(0); n < length; {
2433 var t string
2434 var err error
2435 if t, off, err = unpackText(msg, off); err != nil {
2436 return TXTResource{}, &nestedError{"text", err}
2437 }
2438
2439 if length-n < uint16(len(t))+1 {
2440 return TXTResource{}, errCalcLen
2441 }
2442 n += uint16(len(t)) + 1
2443 txts = append(txts, t)
2444 }
2445 return TXTResource{txts}, nil
2446 }
2447
2448
2449 type SRVResource struct {
2450 Priority uint16
2451 Weight uint16
2452 Port uint16
2453 Target Name
2454 }
2455
2456 func (r *SRVResource) realType() Type {
2457 return TypeSRV
2458 }
2459
2460
2461 func (r *SRVResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
2462 oldMsg := msg
2463 msg = packUint16(msg, r.Priority)
2464 msg = packUint16(msg, r.Weight)
2465 msg = packUint16(msg, r.Port)
2466 msg, err := r.Target.pack(msg, nil, compressionOff)
2467 if err != nil {
2468 return oldMsg, &nestedError{"SRVResource.Target", err}
2469 }
2470 return msg, nil
2471 }
2472
2473
2474 func (r *SRVResource) GoString() string {
2475 return "dnsmessage.SRVResource{" +
2476 "Priority: " + printUint16(r.Priority) + ", " +
2477 "Weight: " + printUint16(r.Weight) + ", " +
2478 "Port: " + printUint16(r.Port) + ", " +
2479 "Target: " + r.Target.GoString() + "}"
2480 }
2481
2482 func unpackSRVResource(msg []byte, off int) (SRVResource, error) {
2483 priority, off, err := unpackUint16(msg, off)
2484 if err != nil {
2485 return SRVResource{}, &nestedError{"Priority", err}
2486 }
2487 weight, off, err := unpackUint16(msg, off)
2488 if err != nil {
2489 return SRVResource{}, &nestedError{"Weight", err}
2490 }
2491 port, off, err := unpackUint16(msg, off)
2492 if err != nil {
2493 return SRVResource{}, &nestedError{"Port", err}
2494 }
2495 var target Name
2496 if _, err := target.unpackCompressed(msg, off, false ); err != nil {
2497 return SRVResource{}, &nestedError{"Target", err}
2498 }
2499 return SRVResource{priority, weight, port, target}, nil
2500 }
2501
2502
2503 type AResource struct {
2504 A [4]byte
2505 }
2506
2507 func (r *AResource) realType() Type {
2508 return TypeA
2509 }
2510
2511
2512 func (r *AResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
2513 return packBytes(msg, r.A[:]), nil
2514 }
2515
2516
2517 func (r *AResource) GoString() string {
2518 return "dnsmessage.AResource{" +
2519 "A: [4]byte{" + printByteSlice(r.A[:]) + "}}"
2520 }
2521
2522 func unpackAResource(msg []byte, off int) (AResource, error) {
2523 var a [4]byte
2524 if _, err := unpackBytes(msg, off, a[:]); err != nil {
2525 return AResource{}, err
2526 }
2527 return AResource{a}, nil
2528 }
2529
2530
2531 type AAAAResource struct {
2532 AAAA [16]byte
2533 }
2534
2535 func (r *AAAAResource) realType() Type {
2536 return TypeAAAA
2537 }
2538
2539
2540 func (r *AAAAResource) GoString() string {
2541 return "dnsmessage.AAAAResource{" +
2542 "AAAA: [16]byte{" + printByteSlice(r.AAAA[:]) + "}}"
2543 }
2544
2545
2546 func (r *AAAAResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
2547 return packBytes(msg, r.AAAA[:]), nil
2548 }
2549
2550 func unpackAAAAResource(msg []byte, off int) (AAAAResource, error) {
2551 var aaaa [16]byte
2552 if _, err := unpackBytes(msg, off, aaaa[:]); err != nil {
2553 return AAAAResource{}, err
2554 }
2555 return AAAAResource{aaaa}, nil
2556 }
2557
2558
2559
2560
2561
2562 type OPTResource struct {
2563 Options []Option
2564 }
2565
2566
2567
2568
2569
2570 type Option struct {
2571 Code uint16
2572 Data []byte
2573 }
2574
2575
2576 func (o *Option) GoString() string {
2577 return "dnsmessage.Option{" +
2578 "Code: " + printUint16(o.Code) + ", " +
2579 "Data: []byte{" + printByteSlice(o.Data) + "}}"
2580 }
2581
2582 func (r *OPTResource) realType() Type {
2583 return TypeOPT
2584 }
2585
2586 func (r *OPTResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
2587 for _, opt := range r.Options {
2588 msg = packUint16(msg, opt.Code)
2589 l := uint16(len(opt.Data))
2590 msg = packUint16(msg, l)
2591 msg = packBytes(msg, opt.Data)
2592 }
2593 return msg, nil
2594 }
2595
2596
2597 func (r *OPTResource) GoString() string {
2598 s := "dnsmessage.OPTResource{Options: []dnsmessage.Option{"
2599 if len(r.Options) == 0 {
2600 return s + "}}"
2601 }
2602 s += r.Options[0].GoString()
2603 for _, o := range r.Options[1:] {
2604 s += ", " + o.GoString()
2605 }
2606 return s + "}}"
2607 }
2608
2609 func unpackOPTResource(msg []byte, off int, length uint16) (OPTResource, error) {
2610 var opts []Option
2611 for oldOff := off; off < oldOff+int(length); {
2612 var err error
2613 var o Option
2614 o.Code, off, err = unpackUint16(msg, off)
2615 if err != nil {
2616 return OPTResource{}, &nestedError{"Code", err}
2617 }
2618 var l uint16
2619 l, off, err = unpackUint16(msg, off)
2620 if err != nil {
2621 return OPTResource{}, &nestedError{"Data", err}
2622 }
2623 o.Data = make([]byte, l)
2624 if copy(o.Data, msg[off:]) != int(l) {
2625 return OPTResource{}, &nestedError{"Data", errCalcLen}
2626 }
2627 off += int(l)
2628 opts = append(opts, o)
2629 }
2630 return OPTResource{opts}, nil
2631 }
2632
2633
2634 type UnknownResource struct {
2635 Type Type
2636 Data []byte
2637 }
2638
2639 func (r *UnknownResource) realType() Type {
2640 return r.Type
2641 }
2642
2643
2644 func (r *UnknownResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
2645 return packBytes(msg, r.Data[:]), nil
2646 }
2647
2648
2649 func (r *UnknownResource) GoString() string {
2650 return "dnsmessage.UnknownResource{" +
2651 "Type: " + r.Type.GoString() + ", " +
2652 "Data: []byte{" + printByteSlice(r.Data) + "}}"
2653 }
2654
2655 func unpackUnknownResource(recordType Type, msg []byte, off int, length uint16) (UnknownResource, error) {
2656 parsed := UnknownResource{
2657 Type: recordType,
2658 Data: make([]byte, length),
2659 }
2660 if _, err := unpackBytes(msg, off, parsed.Data); err != nil {
2661 return UnknownResource{}, err
2662 }
2663 return parsed, nil
2664 }
2665
View as plain text