1package dns 2 3import "strings" 4 5// PrivateRdata is an interface used for implementing "Private Use" RR types, see 6// RFC 6895. This allows one to experiment with new RR types, without requesting an 7// official type code. Also see dns.PrivateHandle and dns.PrivateHandleRemove. 8type PrivateRdata interface { 9 // String returns the text presentation of the Rdata of the Private RR. 10 String() string 11 // Parse parses the Rdata of the private RR. 12 Parse([]string) error 13 // Pack is used when packing a private RR into a buffer. 14 Pack([]byte) (int, error) 15 // Unpack is used when unpacking a private RR from a buffer. 16 Unpack([]byte) (int, error) 17 // Copy copies the Rdata into the PrivateRdata argument. 18 Copy(PrivateRdata) error 19 // Len returns the length in octets of the Rdata. 20 Len() int 21} 22 23// PrivateRR represents an RR that uses a PrivateRdata user-defined type. 24// It mocks normal RRs and implements dns.RR interface. 25type PrivateRR struct { 26 Hdr RR_Header 27 Data PrivateRdata 28 29 generator func() PrivateRdata // for copy 30} 31 32// Header return the RR header of r. 33func (r *PrivateRR) Header() *RR_Header { return &r.Hdr } 34 35func (r *PrivateRR) String() string { return r.Hdr.String() + r.Data.String() } 36 37// Private len and copy parts to satisfy RR interface. 38func (r *PrivateRR) len(off int, compression map[string]struct{}) int { 39 l := r.Hdr.len(off, compression) 40 l += r.Data.Len() 41 return l 42} 43 44func (r *PrivateRR) copy() RR { 45 // make new RR like this: 46 rr := &PrivateRR{r.Hdr, r.generator(), r.generator} 47 48 if err := r.Data.Copy(rr.Data); err != nil { 49 panic("dns: got value that could not be used to copy Private rdata: " + err.Error()) 50 } 51 52 return rr 53} 54 55func (r *PrivateRR) pack(msg []byte, off int, compression compressionMap, compress bool) (int, error) { 56 n, err := r.Data.Pack(msg[off:]) 57 if err != nil { 58 return len(msg), err 59 } 60 off += n 61 return off, nil 62} 63 64func (r *PrivateRR) unpack(msg []byte, off int) (int, error) { 65 off1, err := r.Data.Unpack(msg[off:]) 66 off += off1 67 return off, err 68} 69 70func (r *PrivateRR) parse(c *zlexer, origin string) *ParseError { 71 var l lex 72 text := make([]string, 0, 2) // could be 0..N elements, median is probably 1 73Fetch: 74 for { 75 // TODO(miek): we could also be returning _QUOTE, this might or might not 76 // be an issue (basically parsing TXT becomes hard) 77 switch l, _ = c.Next(); l.value { 78 case zNewline, zEOF: 79 break Fetch 80 case zString: 81 text = append(text, l.token) 82 } 83 } 84 85 err := r.Data.Parse(text) 86 if err != nil { 87 return &ParseError{"", err.Error(), l} 88 } 89 90 return nil 91} 92 93func (r1 *PrivateRR) isDuplicate(r2 RR) bool { return false } 94 95// PrivateHandle registers a private resource record type. It requires 96// string and numeric representation of private RR type and generator function as argument. 97func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) { 98 rtypestr = strings.ToUpper(rtypestr) 99 100 TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator(), generator} } 101 TypeToString[rtype] = rtypestr 102 StringToType[rtypestr] = rtype 103} 104 105// PrivateHandleRemove removes definitions required to support private RR type. 106func PrivateHandleRemove(rtype uint16) { 107 rtypestr, ok := TypeToString[rtype] 108 if ok { 109 delete(TypeToRR, rtype) 110 delete(TypeToString, rtype) 111 delete(StringToType, rtypestr) 112 } 113} 114