1package dns 2 3import ( 4 "encoding/hex" 5 "strconv" 6) 7 8const ( 9 year68 = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits. 10 defaultTtl = 3600 // Default internal TTL. 11 12 // DefaultMsgSize is the standard default for messages larger than 512 bytes. 13 DefaultMsgSize = 4096 14 // MinMsgSize is the minimal size of a DNS packet. 15 MinMsgSize = 512 16 // MaxMsgSize is the largest possible DNS packet. 17 MaxMsgSize = 65535 18) 19 20// Error represents a DNS error. 21type Error struct{ err string } 22 23func (e *Error) Error() string { 24 if e == nil { 25 return "dns: <nil>" 26 } 27 return "dns: " + e.err 28} 29 30// An RR represents a resource record. 31type RR interface { 32 // Header returns the header of an resource record. The header contains 33 // everything up to the rdata. 34 Header() *RR_Header 35 // String returns the text representation of the resource record. 36 String() string 37 38 // copy returns a copy of the RR 39 copy() RR 40 41 // len returns the length (in octets) of the compressed or uncompressed RR in wire format. 42 // 43 // If compression is nil, the uncompressed size will be returned, otherwise the compressed 44 // size will be returned and domain names will be added to the map for future compression. 45 len(off int, compression map[string]struct{}) int 46 47 // pack packs the records RDATA into wire format. The header will 48 // already have been packed into msg. 49 pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) 50 51 // unpack unpacks an RR from wire format. 52 // 53 // This will only be called on a new and empty RR type with only the header populated. It 54 // will only be called if the record's RDATA is non-empty. 55 unpack(msg []byte, off int) (off1 int, err error) 56 57 // parse parses an RR from zone file format. 58 // 59 // This will only be called on a new and empty RR type with only the header populated. 60 parse(c *zlexer, origin string) *ParseError 61 62 // isDuplicate returns whether the two RRs are duplicates. 63 isDuplicate(r2 RR) bool 64} 65 66// RR_Header is the header all DNS resource records share. 67type RR_Header struct { 68 Name string `dns:"cdomain-name"` 69 Rrtype uint16 70 Class uint16 71 Ttl uint32 72 Rdlength uint16 // Length of data after header. 73} 74 75// Header returns itself. This is here to make RR_Header implements the RR interface. 76func (h *RR_Header) Header() *RR_Header { return h } 77 78// Just to implement the RR interface. 79func (h *RR_Header) copy() RR { return nil } 80 81func (h *RR_Header) String() string { 82 var s string 83 84 if h.Rrtype == TypeOPT { 85 s = ";" 86 // and maybe other things 87 } 88 89 s += sprintName(h.Name) + "\t" 90 s += strconv.FormatInt(int64(h.Ttl), 10) + "\t" 91 s += Class(h.Class).String() + "\t" 92 s += Type(h.Rrtype).String() + "\t" 93 return s 94} 95 96func (h *RR_Header) len(off int, compression map[string]struct{}) int { 97 l := domainNameLen(h.Name, off, compression, true) 98 l += 10 // rrtype(2) + class(2) + ttl(4) + rdlength(2) 99 return l 100} 101 102func (h *RR_Header) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) { 103 // RR_Header has no RDATA to pack. 104 return off, nil 105} 106 107func (h *RR_Header) unpack(msg []byte, off int) (int, error) { 108 panic("dns: internal error: unpack should never be called on RR_Header") 109} 110 111func (h *RR_Header) parse(c *zlexer, origin string) *ParseError { 112 panic("dns: internal error: parse should never be called on RR_Header") 113} 114 115// ToRFC3597 converts a known RR to the unknown RR representation from RFC 3597. 116func (rr *RFC3597) ToRFC3597(r RR) error { 117 buf := make([]byte, Len(r)) 118 headerEnd, off, err := packRR(r, buf, 0, compressionMap{}, false) 119 if err != nil { 120 return err 121 } 122 buf = buf[:off] 123 124 *rr = RFC3597{Hdr: *r.Header()} 125 rr.Hdr.Rdlength = uint16(off - headerEnd) 126 127 if noRdata(rr.Hdr) { 128 return nil 129 } 130 131 _, err = rr.unpack(buf, headerEnd) 132 return err 133} 134 135// fromRFC3597 converts an unknown RR representation from RFC 3597 to the known RR type. 136func (rr *RFC3597) fromRFC3597(r RR) error { 137 hdr := r.Header() 138 *hdr = rr.Hdr 139 140 // Can't overflow uint16 as the length of Rdata is validated in (*RFC3597).parse. 141 // We can only get here when rr was constructed with that method. 142 hdr.Rdlength = uint16(hex.DecodedLen(len(rr.Rdata))) 143 144 if noRdata(*hdr) { 145 // Dynamic update. 146 return nil 147 } 148 149 // rr.pack requires an extra allocation and a copy so we just decode Rdata 150 // manually, it's simpler anyway. 151 msg, err := hex.DecodeString(rr.Rdata) 152 if err != nil { 153 return err 154 } 155 156 _, err = r.unpack(msg, 0) 157 return err 158} 159