-
-
Notifications
You must be signed in to change notification settings - Fork 131
/
OptRecord.cs
147 lines (128 loc) · 5.54 KB
/
OptRecord.cs
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Net;
namespace DnsClient.Protocol.Options
{
/* https://tools.ietf.org/html/rfc6891#section-4.3
6.1.2. Wire Format
An OPT RR has a fixed part and a variable set of options expressed as
{attribute, value} pairs. The fixed part holds some DNS metadata,
and also a small collection of basic extension elements that we
expect to be so popular that it would be a waste of wire space to
encode them as {attribute, value} pairs.
The fixed part of an OPT RR is structured as follows:
+------------+--------------+------------------------------+
| Field Name | Field Type | Description |
+------------+--------------+------------------------------+
| NAME | domain name | MUST be 0 (root domain) |
| TYPE | u_int16_t | OPT (41) |
| CLASS | u_int16_t | requestor's UDP payload size |
| TTL | u_int32_t | extended RCODE and flags |
| RDLEN | u_int16_t | length of all RDATA |
| RDATA | octet stream | {attribute,value} pairs |
+------------+--------------+------------------------------+
6.1.3. OPT Record TTL Field Use
The extended RCODE and flags, which OPT stores in the RR Time to Live
(TTL) field, are structured as follows:
+0 (MSB) +1 (LSB)
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
0: | EXTENDED-RCODE | VERSION |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
2: | DO| Z |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
DO flag => https://tools.ietf.org/html/rfc3225
EXTENDED-RCODE
Forms the upper 8 bits of extended 12-bit RCODE (together with the
4 bits defined in [RFC1035]. Note that EXTENDED-RCODE value 0
indicates that an unextended RCODE is in use (values 0 through
15).
VERSION
Indicates the implementation level of the setter. Full
conformance with this specification is indicated by version '0'.
Requestors are encouraged to set this to the lowest implemented
level capable of expressing a transaction, to minimise the
responder and network load of discovering the greatest common
implementation level between requestor and responder. A
requestor's version numbering strategy MAY ideally be a run-time
configuration option.
If a responder does not implement the VERSION level of the
request, then it MUST respond with RCODE=BADVERS. All responses
MUST be limited in format to the VERSION level of the request, but
the VERSION of each response SHOULD be the highest implementation
level of the responder. In this way, a requestor will learn the
implementation level of a responder as a side effect of every
response, including error responses and including RCODE=BADVERS.
*/
/// <summary>
/// A options resource record.
/// </summary>
public class OptRecord : DnsResourceRecord
{
private const uint ResponseCodeMask = 0xff000000;
private const int ResponseCodeShift = 20;
private const uint VersionMask = 0x00ff0000;
private const int VersionShift = 16;
public DnsResponseCode ResponseCodeEx
{
get
{
return (DnsResponseCode)((InitialTimeToLive & ResponseCodeMask) >> ResponseCodeShift);
}
set
{
InitialTimeToLive &= (int)~ResponseCodeMask;
InitialTimeToLive |= (int)(((int)value << ResponseCodeShift) & ResponseCodeMask);
}
}
public short UdpSize
{
get { return (short)RecordClass; }
}
public byte Version
{
get
{
return (byte)((InitialTimeToLive & VersionMask) >> VersionShift);
}
set
{
InitialTimeToLive = (int)((uint)InitialTimeToLive & ~VersionMask);
InitialTimeToLive |= (int)((value << VersionShift) & VersionMask);
}
}
public bool IsDnsSecOk
{
get { return (InitialTimeToLive & 0x8000) != 0; }
set
{
if (value)
{
InitialTimeToLive |= 0x8000;
}
else
{
InitialTimeToLive &= 0x7fff;
}
}
}
public byte[] Data { get; }
// used to initiate
public OptRecord(int size = 4096, int version = 0, bool doFlag = false, int length = 0, byte[] data = null)
: base(new ResourceRecordInfo(DnsString.RootLabel, ResourceRecordType.OPT, (QueryClass)size, version, length))
{
Data = data;
IsDnsSecOk = doFlag;
}
// returned record
public OptRecord(int size, int ttlFlag, int length, byte[] data)
: base(new ResourceRecordInfo(DnsString.RootLabel, ResourceRecordType.OPT, (QueryClass)size, ttlFlag, length))
{
Data = data;
}
private protected override string RecordToString()
{
return $"OPT {RecordClass}.";
}
}
}
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member