9
9
#define DEBUG_OUTPUT Serial
10
10
#endif
11
11
12
- DNSServer::DNSServer () : _port(0 ), _ttl(htonl(DNS_DEFAULT_TTL)), _errorReplyCode(DNSReplyCode::NonExistentDomain)
13
- {
14
- _dnsHeader = new DNSHeader ();
15
- _dnsQuestion = new DNSQuestion ();
16
- }
12
+ DNSServer::DNSServer () : _port(0 ), _ttl(htonl(DNS_DEFAULT_TTL)), _errorReplyCode(DNSReplyCode::NonExistentDomain){}
17
13
18
- DNSServer::~DNSServer ()
19
- {
20
- if (_dnsHeader) {
21
- delete _dnsHeader;
22
- _dnsHeader = nullptr ;
23
- }
24
- if (_dnsQuestion) {
25
- delete _dnsQuestion;
26
- _dnsQuestion = nullptr ;
27
- }
28
- }
14
+ DNSServer::~DNSServer (){}
29
15
30
16
bool DNSServer::start (const uint16_t &port, const String &domainName,
31
17
const IPAddress &resolvedIP)
@@ -37,6 +23,7 @@ bool DNSServer::start(const uint16_t &port, const String &domainName,
37
23
_resolvedIP[2 ] = resolvedIP[2 ];
38
24
_resolvedIP[3 ] = resolvedIP[3 ];
39
25
downcaseAndRemoveWwwPrefix (_domainName);
26
+ _udp.close ();
40
27
_udp.onPacket ([this ](AsyncUDPPacket& pkt){ this ->_handleUDP (pkt); });
41
28
return _udp.listen (_port);
42
29
}
@@ -64,70 +51,58 @@ void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName)
64
51
65
52
void DNSServer::_handleUDP (AsyncUDPPacket& pkt)
66
53
{
67
- size_t _currentPacketSize = pkt.length ();
68
- if (_currentPacketSize < DNS_HEADER_SIZE) return ;
54
+ size_t currentPacketSize = pkt.length ();
55
+ if (currentPacketSize < DNS_HEADER_SIZE) return ;
69
56
70
57
// get DNS header (beginning of message)
71
- memcpy ( _dnsHeader, pkt.data (), DNS_HEADER_SIZE );
72
- if (_dnsHeader->QR != DNS_QR_QUERY) return ; // ignore non-query mesages
58
+ DNSHeader dnsHeader;
59
+ DNSQuestion dnsQuestion;
60
+ memcpy ( &dnsHeader, pkt.data (), DNS_HEADER_SIZE );
61
+ if (dnsHeader.QR != DNS_QR_QUERY) return ; // ignore non-query mesages
73
62
74
- if ( requestIncludesOnlyOneQuestion () )
63
+ if ( requestIncludesOnlyOneQuestion (dnsHeader ) )
75
64
{
65
+ /*
66
+ // The QName has a variable length, maximum 255 bytes and is comprised of multiple labels.
67
+ // Each label contains a byte to describe its length and the label itself. The list of
68
+ // labels terminates with a zero-valued byte. In "github.com", we have two labels "github" & "com"
69
+ */
76
70
char * enoflbls = strchr ((const char *)pkt.data () + DNS_HEADER_SIZE, 0 ); // find end_of_label marker
77
71
++enoflbls; // include null terminator
78
- _dnsQuestion-> QName = pkt.data () + DNS_HEADER_SIZE; // we can reference labels from the request
79
- _dnsQuestion-> QNameLength = enoflbls - (char *)pkt.data () - DNS_HEADER_SIZE;
72
+ dnsQuestion. QName = pkt.data () + DNS_HEADER_SIZE; // we can reference labels from the request
73
+ dnsQuestion. QNameLength = enoflbls - (char *)pkt.data () - DNS_HEADER_SIZE;
80
74
/*
81
75
check if we aint going out of pkt bounds
82
76
proper dns req should have label terminator at least 4 bytes before end of packet
83
77
*/
84
- if (_dnsQuestion-> QNameLength > _currentPacketSize - sizeof (_dnsQuestion-> QType ) - sizeof (_dnsQuestion-> QClass )) return ; // malformed packet
78
+ if (dnsQuestion. QNameLength > currentPacketSize - sizeof (dnsQuestion. QType ) - sizeof (dnsQuestion. QClass )) return ; // malformed packet
85
79
86
80
// Copy the QType and QClass
87
- memcpy ( &_dnsQuestion->QType , enoflbls, sizeof (_dnsQuestion->QType ) );
88
- memcpy ( &_dnsQuestion->QClass , enoflbls + sizeof (_dnsQuestion->QType ), sizeof (_dnsQuestion->QClass ) );
89
-
90
- /*
91
- // The QName has a variable length, maximum 255 bytes and is comprised of multiple labels.
92
- // Each label contains a byte to describe its length and the label itself. The list of
93
- // labels terminates with a zero-valued byte. In "github.com", we have two labels "github" & "com"
94
- // Iterate through the labels and copy them as they come into a single buffer (for simplicity's sake)
95
- _dnsQuestion->QNameLength = 0 ;
96
- while ( _buffer[ DNS_HEADER_SIZE + _dnsQuestion->QNameLength ] != 0 )
97
- {
98
- memcpy( (void*) &_dnsQuestion->QName[_dnsQuestion->QNameLength], (void*) &_buffer[DNS_HEADER_SIZE + _dnsQuestion->QNameLength], _buffer[DNS_HEADER_SIZE + _dnsQuestion->QNameLength] + 1 ) ;
99
- _dnsQuestion->QNameLength += _buffer[DNS_HEADER_SIZE + _dnsQuestion->QNameLength] + 1 ;
100
- }
101
- _dnsQuestion->QName[_dnsQuestion->QNameLength] = 0 ;
102
- _dnsQuestion->QNameLength++ ;
103
-
104
- // Copy the QType and QClass
105
- memcpy( &_dnsQuestion->QType, (void*) &_buffer[DNS_HEADER_SIZE + _dnsQuestion->QNameLength], sizeof(_dnsQuestion->QType) ) ;
106
- memcpy( &_dnsQuestion->QClass, (void*) &_buffer[DNS_HEADER_SIZE + _dnsQuestion->QNameLength + sizeof(_dnsQuestion->QType)], sizeof(_dnsQuestion->QClass) ) ;
107
- */
81
+ memcpy ( &dnsQuestion.QType , enoflbls, sizeof (dnsQuestion.QType ) );
82
+ memcpy ( &dnsQuestion.QClass , enoflbls + sizeof (dnsQuestion.QType ), sizeof (dnsQuestion.QClass ) );
108
83
}
109
-
84
+
110
85
// will reply with IP only to "*" or if doman matches without www. subdomain
111
- if (_dnsHeader-> OPCode == DNS_OPCODE_QUERY &&
112
- requestIncludesOnlyOneQuestion () &&
86
+ if (dnsHeader. OPCode == DNS_OPCODE_QUERY &&
87
+ requestIncludesOnlyOneQuestion (dnsHeader ) &&
113
88
(_domainName == " *" ||
114
- getDomainNameWithoutWwwPrefix ((const char *)pkt.data () + DNS_HEADER_SIZE, _dnsQuestion-> QNameLength ) == _domainName)
89
+ getDomainNameWithoutWwwPrefix ((const char *)pkt.data () + DNS_HEADER_SIZE, dnsQuestion. QNameLength ) == _domainName)
115
90
)
116
91
{
117
- replyWithIP (pkt);
92
+ replyWithIP (pkt, dnsHeader, dnsQuestion );
118
93
return ;
119
94
}
120
95
121
96
// otherwise reply with custom code
122
- replyWithCustomCode (pkt);
97
+ replyWithCustomCode (pkt, dnsHeader );
123
98
}
124
99
125
- bool DNSServer::requestIncludesOnlyOneQuestion ()
100
+ bool DNSServer::requestIncludesOnlyOneQuestion (DNSHeader& dnsHeader )
126
101
{
127
- return ntohs (_dnsHeader-> QDCount ) == 1 &&
128
- _dnsHeader-> ANCount == 0 &&
129
- _dnsHeader-> NSCount == 0 &&
130
- _dnsHeader-> ARCount == 0 ;
102
+ return ntohs (dnsHeader. QDCount ) == 1 &&
103
+ dnsHeader. ANCount == 0 &&
104
+ dnsHeader. NSCount == 0 &&
105
+ dnsHeader. ARCount == 0 ;
131
106
}
132
107
133
108
@@ -164,20 +139,20 @@ String DNSServer::getDomainNameWithoutWwwPrefix(const char* start, size_t len)
164
139
}
165
140
}
166
141
167
- void DNSServer::replyWithIP (AsyncUDPPacket& req)
142
+ void DNSServer::replyWithIP (AsyncUDPPacket& req, DNSHeader& dnsHeader, DNSQuestion& dnsQuestion )
168
143
{
169
144
AsyncUDPMessage rpl;
170
145
171
146
// Change the type of message to a response and set the number of answers equal to
172
147
// the number of questions in the header
173
- _dnsHeader-> QR = DNS_QR_RESPONSE;
174
- _dnsHeader-> ANCount = _dnsHeader-> QDCount ;
175
- rpl.write ( (unsigned char *) _dnsHeader , DNS_HEADER_SIZE ) ;
148
+ dnsHeader. QR = DNS_QR_RESPONSE;
149
+ dnsHeader. ANCount = dnsHeader. QDCount ;
150
+ rpl.write ( (unsigned char *) &dnsHeader , DNS_HEADER_SIZE ) ;
176
151
177
152
// Write the question
178
- rpl.write (_dnsQuestion-> QName , _dnsQuestion-> QNameLength ) ;
179
- rpl.write ( (uint8_t *) &_dnsQuestion-> QType , 2 ) ;
180
- rpl.write ( (uint8_t *) &_dnsQuestion-> QClass , 2 ) ;
153
+ rpl.write (dnsQuestion. QName , dnsQuestion. QNameLength ) ;
154
+ rpl.write ( (uint8_t *) &dnsQuestion. QType , 2 ) ;
155
+ rpl.write ( (uint8_t *) &dnsQuestion. QClass , 2 ) ;
181
156
182
157
// Write the answer
183
158
// Use DNS name compression : instead of repeating the name in this RNAME occurence,
@@ -199,17 +174,17 @@ void DNSServer::replyWithIP(AsyncUDPPacket& req)
199
174
200
175
#ifdef DEBUG_ESP_DNS
201
176
DEBUG_OUTPUT.printf (" DNS responds: %s for %s\n " ,
202
- IPAddress (_resolvedIP).toString ().c_str (), getDomainNameWithoutWwwPrefix ((const char *)rpl.data () + DNS_HEADER_SIZE, _dnsQuestion-> QNameLength ).c_str () );
177
+ IPAddress (_resolvedIP).toString ().c_str (), getDomainNameWithoutWwwPrefix ((const char *)rpl.data () + DNS_HEADER_SIZE, dnsQuestion. QNameLength ).c_str () );
203
178
#endif
204
179
}
205
180
206
- void DNSServer::replyWithCustomCode (AsyncUDPPacket& req)
181
+ void DNSServer::replyWithCustomCode (AsyncUDPPacket& req, DNSHeader& dnsHeader )
207
182
{
208
- _dnsHeader-> QR = DNS_QR_RESPONSE;
209
- _dnsHeader-> RCode = (uint16_t )_errorReplyCode;
210
- _dnsHeader-> QDCount = 0 ;
183
+ dnsHeader. QR = DNS_QR_RESPONSE;
184
+ dnsHeader. RCode = (uint16_t )_errorReplyCode;
185
+ dnsHeader. QDCount = 0 ;
211
186
212
187
AsyncUDPMessage rpl (sizeof (DNSHeader));
213
- rpl.write ((unsigned char *)_dnsHeader , sizeof (DNSHeader));
188
+ rpl.write ((unsigned char *)&dnsHeader , sizeof (DNSHeader));
214
189
_udp.sendTo (rpl, req.remoteIP (), req.remotePort ());
215
190
}
0 commit comments