privaterr.go (3302B)
1 package dns 2 3 import "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. 8 type 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. 25 type 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. 33 func (r *PrivateRR) Header() *RR_Header { return &r.Hdr } 34 35 func (r *PrivateRR) String() string { return r.Hdr.String() + r.Data.String() } 36 37 // Private len and copy parts to satisfy RR interface. 38 func (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 44 func (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 55 func (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 64 func (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 70 func (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 73 Fetch: 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 93 func (r *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. 97 func 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. 106 func 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 }