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