func unpackRR(msg []byte, off int) (rr RR, off1 int, ok bool) {
	var h RR_Header
	off0 := off
	if off, ok = unpackStruct(&h, msg, off); !ok {
		return nil, len(msg), false
	}
	end := off + int(h.Rdlength)
	if end < len(msg) {
		msg = msg[:end]
	}
	mk, known := rr_mk[int(h.Rrtype)]
	if !known {
		return &h, end, true
	}
	rr = mk()
	off, ok = unpackStruct(rr, msg, off0)
	if off != end {
		return &h, end, true
	}
	return rr, off, ok
}
Resource record unpacker.
package dns
import (
	"net"
	"strconv"
)
const (
	TypeA     = 1
	TypeNS    = 2
	TypeMD    = 3
	TypeMF    = 4
	TypeCNAME = 5
	TypeSOA   = 6
	TypeMB    = 7
	TypeMG    = 8
	TypeMR    = 9
	TypeNULL  = 10
	TypeWKS   = 11
	TypePTR   = 12
	TypeHINFO = 13
	TypeMINFO = 14
	TypeMX    = 15
	TypeTXT   = 16
	TypeAAAA  = 28
	TypeSRV   = 33
	TypeAXFR  = 252
	TypeMAILB = 253
	TypeMAILA = 254
	TypeALL   = 255
	ClassINET   = 1
	ClassCSNET  = 2
	ClassCHAOS  = 3
	ClassHESIOD = 4
	ClassANY    = 255
	RcodeSuccess        = 0
	RcodeFormatError    = 1
	RcodeServerFailure  = 2
	RcodeNameError      = 3
	RcodeNotImplemented = 4
	RcodeRefused        = 5
)
type dnsStruct interface {
	Walk(f func(v interface{}, name, tag string) (ok bool)) (ok bool)
}
type dnsHeader struct {
	Id                                 uint16
	Bits                               uint16
	Qdcount, Ancount, Nscount, Arcount uint16
}
func (h *dnsHeader) Walk(f func(v interface{}, name, tag string) bool) bool {
	return f(&h.Id, "Id", "") &&
		f(&h.Bits, "Bits", "") &&
		f(&h.Qdcount, "Qdcount", "") &&
		f(&h.Ancount, "Ancount", "") &&
		f(&h.Nscount, "Nscount", "") &&
		f(&h.Arcount, "Arcount", "")
}
const (
	_QR = 1 << 15  
	_AA = 1 << 10  
	_TC = 1 << 9   
	_RD = 1 << 8   
	_RA = 1 << 7   
)
type Question struct {
	Name   string `net:"domain-name"`  
	Qtype  uint16
	Qclass uint16
}
func (q *Question) Walk(f func(v interface{}, name, tag string) bool) bool {
	return f(&q.Name, "Name", "domain") &&
		f(&q.Qtype, "Qtype", "") &&
		f(&q.Qclass, "Qclass", "")
}
type RR_Header struct {
	Name     string `net:"domain-name"`
	Rrtype   uint16
	Class    uint16
	Ttl      uint32
	Rdlength uint16  
}
func (h *RR_Header) Header() *RR_Header {
	return h
}
func (h *RR_Header) Walk(f func(v interface{}, name, tag string) bool) bool {
	return f(&h.Name, "Name", "domain") &&
		f(&h.Rrtype, "Rrtype", "") &&
		f(&h.Class, "Class", "") &&
		f(&h.Ttl, "Ttl", "") &&
		f(&h.Rdlength, "Rdlength", "")
}
type RR interface {
	dnsStruct
	Header() *RR_Header
}
type RR_CNAME struct {
	Hdr   RR_Header
	Cname string `net:"domain-name"`
}
func (rr *RR_CNAME) Header() *RR_Header {
	return &rr.Hdr
}
func (rr *RR_CNAME) Walk(f func(v interface{}, name, tag string) bool) bool {
	return rr.Hdr.Walk(f) && f(&rr.Cname, "Cname", "domain")
}
type RR_HINFO struct {
	Hdr RR_Header
	Cpu string
	Os  string
}
func (rr *RR_HINFO) Header() *RR_Header {
	return &rr.Hdr
}
func (rr *RR_HINFO) Walk(f func(v interface{}, name, tag string) bool) bool {
	return rr.Hdr.Walk(f) && f(&rr.Cpu, "Cpu", "") && f(&rr.Os, "Os", "")
}
type RR_MB struct {
	Hdr RR_Header
	Mb  string `net:"domain-name"`
}
func (rr *RR_MB) Header() *RR_Header {
	return &rr.Hdr
}
func (rr *RR_MB) Walk(f func(v interface{}, name, tag string) bool) bool {
	return rr.Hdr.Walk(f) && f(&rr.Mb, "Mb", "domain")
}
type RR_MG struct {
	Hdr RR_Header
	Mg  string `net:"domain-name"`
}
func (rr *RR_MG) Header() *RR_Header {
	return &rr.Hdr
}
func (rr *RR_MG) Walk(f func(v interface{}, name, tag string) bool) bool {
	return rr.Hdr.Walk(f) && f(&rr.Mg, "Mg", "domain")
}
type RR_MINFO struct {
	Hdr   RR_Header
	Rmail string `net:"domain-name"`
	Email string `net:"domain-name"`
}
func (rr *RR_MINFO) Header() *RR_Header {
	return &rr.Hdr
}
func (rr *RR_MINFO) Walk(f func(v interface{}, name, tag string) bool) bool {
	return rr.Hdr.Walk(f) && f(&rr.Rmail, "Rmail", "domain") && f(&rr.Email, "Email", "domain")
}
type RR_MR struct {
	Hdr RR_Header
	Mr  string `net:"domain-name"`
}
func (rr *RR_MR) Header() *RR_Header {
	return &rr.Hdr
}
func (rr *RR_MR) Walk(f func(v interface{}, name, tag string) bool) bool {
	return rr.Hdr.Walk(f) && f(&rr.Mr, "Mr", "domain")
}
type RR_MX struct {
	Hdr  RR_Header
	Pref uint16
	Mx   string `net:"domain-name"`
}
func (rr *RR_MX) Header() *RR_Header {
	return &rr.Hdr
}
func (rr *RR_MX) Walk(f func(v interface{}, name, tag string) bool) bool {
	return rr.Hdr.Walk(f) && f(&rr.Pref, "Pref", "") && f(&rr.Mx, "Mx", "domain")
}
type RR_NS struct {
	Hdr RR_Header
	Ns  string `net:"domain-name"`
}
func (rr *RR_NS) Header() *RR_Header {
	return &rr.Hdr
}
func (rr *RR_NS) Walk(f func(v interface{}, name, tag string) bool) bool {
	return rr.Hdr.Walk(f) && f(&rr.Ns, "Ns", "domain")
}
type RR_PTR struct {
	Hdr RR_Header
	Ptr string `net:"domain-name"`
}
func (rr *RR_PTR) Header() *RR_Header {
	return &rr.Hdr
}
func (rr *RR_PTR) Walk(f func(v interface{}, name, tag string) bool) bool {
	return rr.Hdr.Walk(f) && f(&rr.Ptr, "Ptr", "domain")
}
type RR_SOA struct {
	Hdr     RR_Header
	Ns      string `net:"domain-name"`
	Mbox    string `net:"domain-name"`
	Serial  uint32
	Refresh uint32
	Retry   uint32
	Expire  uint32
	Minttl  uint32
}
func (rr *RR_SOA) Header() *RR_Header {
	return &rr.Hdr
}
func (rr *RR_SOA) Walk(f func(v interface{}, name, tag string) bool) bool {
	return rr.Hdr.Walk(f) &&
		f(&rr.Ns, "Ns", "domain") &&
		f(&rr.Mbox, "Mbox", "domain") &&
		f(&rr.Serial, "Serial", "") &&
		f(&rr.Refresh, "Refresh", "") &&
		f(&rr.Retry, "Retry", "") &&
		f(&rr.Expire, "Expire", "") &&
		f(&rr.Minttl, "Minttl", "")
}
type RR_TXT struct {
	Hdr RR_Header
	Txt []string
}
func (rr *RR_TXT) Header() *RR_Header {
	return &rr.Hdr
}
func (rr *RR_TXT) Walk(f func(v interface{}, name, tag string) bool) bool {
	return rr.Hdr.Walk(f) && f(&rr.Txt, "Txt", "")
}
type RR_SRV struct {
	Hdr      RR_Header
	Priority uint16
	Weight   uint16
	Port     uint16
	Target   string `net:"domain-name"`
}
func (rr *RR_SRV) Header() *RR_Header {
	return &rr.Hdr
}
func (rr *RR_SRV) Walk(f func(v interface{}, name, tag string) bool) bool {
	return rr.Hdr.Walk(f) &&
		f(&rr.Priority, "Priority", "") &&
		f(&rr.Weight, "Weight", "") &&
		f(&rr.Port, "Port", "") &&
		f(&rr.Target, "Target", "domain")
}
type RR_A struct {
	Hdr RR_Header
	A   uint32 `net:"ipv4"`
}
func (rr *RR_A) Header() *RR_Header {
	return &rr.Hdr
}
func (rr *RR_A) Walk(f func(v interface{}, name, tag string) bool) bool {
	return rr.Hdr.Walk(f) && f(&rr.A, "A", "ipv4")
}
type RR_AAAA struct {
	Hdr  RR_Header
	AAAA [16]byte `net:"ipv6"`
}
func (rr *RR_AAAA) Header() *RR_Header {
	return &rr.Hdr
}
func (rr *RR_AAAA) Walk(f func(v interface{}, name, tag string) bool) bool {
	return rr.Hdr.Walk(f) && f(rr.AAAA[:], "AAAA", "ipv6")
}
var rr_mk = map[int]func() RR{
	TypeCNAME: func() RR { return new(RR_CNAME) },
	TypeHINFO: func() RR { return new(RR_HINFO) },
	TypeMB:    func() RR { return new(RR_MB) },
	TypeMG:    func() RR { return new(RR_MG) },
	TypeMINFO: func() RR { return new(RR_MINFO) },
	TypeMR:    func() RR { return new(RR_MR) },
	TypeMX:    func() RR { return new(RR_MX) },
	TypeNS:    func() RR { return new(RR_NS) },
	TypePTR:   func() RR { return new(RR_PTR) },
	TypeSOA:   func() RR { return new(RR_SOA) },
	TypeTXT:   func() RR { return new(RR_TXT) },
	TypeSRV:   func() RR { return new(RR_SRV) },
	TypeA:     func() RR { return new(RR_A) },
	TypeAAAA:  func() RR { return new(RR_AAAA) },
}
func packDomainName(s string, msg []byte, off int) (off1 int, ok bool) {
	if n := len(s); n == 0 || s[n-1] != '.' {
		s += "."
	}
	tot := len(s) + 1
	if off+tot > len(msg) {
		return len(msg), false
	}
	begin := 0
	for i := 0; i < len(s); i++ {
		if s[i] == '.' {
			if i-begin >= 1<<6 {  
				return len(msg), false
			}
			msg[off] = byte(i - begin)
			off++
			for j := begin; j < i; j++ {
				msg[off] = s[j]
				off++
			}
			begin = i + 1
		}
	}
	msg[off] = 0
	off++
	return off, true
}
func unpackDomainName(msg []byte, off int) (s string, off1 int, ok bool) {
	s = ""
	ptr := 0  
Loop:
	for {
		if off >= len(msg) {
			return "", len(msg), false
		}
		c := int(msg[off])
		off++
		switch c & 0xC0 {
		case 0x00:
			if c == 0x00 {
				break Loop
			}
			if off+c > len(msg) {
				return "", len(msg), false
			}
			s += string(msg[off:off+c]) + "."
			off += c
		case 0xC0:
			if off >= len(msg) {
				return "", len(msg), false
			}
			c1 := msg[off]
			off++
			if ptr == 0 {
				off1 = off
			}
			if ptr++; ptr > 10 {
				return "", len(msg), false
			}
			off = (c^0xC0)<<8 | int(c1)
		default:
			return "", len(msg), false
		}
	}
	if ptr == 0 {
		off1 = off
	}
	return s, off1, true
}
func packStruct(any dnsStruct, msg []byte, off int) (off1 int, ok bool) {
	ok = any.Walk(func(field interface{}, name, tag string) bool {
		switch fv := field.(type) {
		default:
			println("net: dns: unknown packing type")
			return false
		case *uint16:
			i := *fv
			if off+2 > len(msg) {
				return false
			}
			msg[off] = byte(i >> 8)
			msg[off+1] = byte(i)
			off += 2
		case *uint32:
			i := *fv
			msg[off] = byte(i >> 24)
			msg[off+1] = byte(i >> 16)
			msg[off+2] = byte(i >> 8)
			msg[off+3] = byte(i)
			off += 4
		case []byte:
			n := len(fv)
			if off+n > len(msg) {
				return false
			}
			copy(msg[off:off+n], fv)
			off += n
		case *string:
			s := *fv
			switch tag {
			default:
				println("net: dns: unknown string tag", tag)
				return false
			case "domain":
				off, ok = packDomainName(s, msg, off)
				if !ok {
					return false
				}
			case "":
				if len(s) > 255 || off+1+len(s) > len(msg) {
					return false
				}
				msg[off] = byte(len(s))
				off++
				off += copy(msg[off:], s)
			}
		case *[]string:
			if *fv == nil {
				return false
			}
			for _, s := range *fv {
				if len(s) > 255 || off+1+len(s) > len(msg) {
					return false
				}
				msg[off] = byte(len(s))
				off++
				off += copy(msg[off:], s)
			}
		}
		return true
	})
	if !ok {
		return len(msg), false
	}
	return off, true
}
func unpackStruct(any dnsStruct, msg []byte, off int) (off1 int, ok bool) {
	ok = any.Walk(func(field interface{}, name, tag string) bool {
		switch fv := field.(type) {
		default:
			println("net: dns: unknown packing type")
			return false
		case *uint16:
			if off+2 > len(msg) {
				return false
			}
			*fv = uint16(msg[off])<<8 | uint16(msg[off+1])
			off += 2
		case *uint32:
			if off+4 > len(msg) {
				return false
			}
			*fv = uint32(msg[off])<<24 | uint32(msg[off+1])<<16 |
				uint32(msg[off+2])<<8 | uint32(msg[off+3])
			off += 4
		case []byte:
			n := len(fv)
			if off+n > len(msg) {
				return false
			}
			copy(fv, msg[off:off+n])
			off += n
		case *string:
			var s string
			switch tag {
			default:
				println("net: dns: unknown string tag", tag)
				return false
			case "domain":
				s, off, ok = unpackDomainName(msg, off)
				if !ok {
					return false
				}
			case "":
				if off >= len(msg) || off+1+int(msg[off]) > len(msg) {
					return false
				}
				n := int(msg[off])
				off++
				s = string(msg[off : off+n])
				off += n
			}
			*fv = s
		case *[]string:
			for off != len(msg) {
				if off > len(msg) || off+1+int(msg[off]) > len(msg) {
					return false
				}
				n := int(msg[off])
				off++
				*fv = append(*fv, string(msg[off:off+n]))
				off += n
			}
			if *fv == nil {
				return false
			}
		}
		return true
	})
	if !ok {
		return len(msg), false
	}
	return off, true
}
func printStruct(any dnsStruct) string {
	s := "{"
	i := 0
	any.Walk(func(val interface{}, name, tag string) bool {
		i++
		if i > 1 {
			s += ", "
		}
		s += name + "="
		switch tag {
		case "ipv4":
			i := *val.(*uint32)
			s += net.IPv4(byte(i>>24), byte(i>>16), byte(i>>8), byte(i)).String()
		case "ipv6":
			i := val.([]byte)
			s += net.IP(i).String()
		default:
			var i int64
			switch v := val.(type) {
			default:
				s += "<unknown type>"
				return true
			case *string:
				s += *v
				return true
			case *[]string:
				for _, x := range *v {
					s += x + " "
				}
				return true
			case []byte:
				s += string(v)
				return true
			case *bool:
				if *v {
					s += "true"
				} else {
					s += "false"
				}
				return true
			case *int:
				i = int64(*v)
			case *uint:
				i = int64(*v)
			case *uint8:
				i = int64(*v)
			case *uint16:
				i = int64(*v)
			case *uint32:
				i = int64(*v)
			case *uint64:
				i = int64(*v)
			case *uintptr:
				i = int64(*v)
			}
			s += strconv.Itoa(int(i))
		}
		return true
	})
	s += "}"
	return s
}
func packRR(rr RR, msg []byte, off int) (off2 int, ok bool) {
	var off1 int
	off1, ok = packStruct(rr.Header(), msg, off)
	off2, ok = packStruct(rr, msg, off)
	if !ok {
		return len(msg), false
	}
	rr.Header().Rdlength = uint16(off2 - off1)
	packStruct(rr.Header(), msg, off)
	return off2, true
}