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