E-MailRelay

gdnsmessage.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2024 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file gdnsmessage.cpp
19///
20
21#include "gdef.h"
22#include "gdnsmessage.h"
23#include "gassert.h"
24#include "gstr.h"
25#include "gstringview.h"
26#include "gstringfield.h"
27#include <array>
28#include <vector>
29#include <iomanip>
30#include <sstream>
31#include <stdexcept>
32
33 GNet::DnsMessageRequest::DnsMessageRequest( const std::string & type , const std::string & hostname , unsigned int id )
34{
35 // header section
36 G_ASSERT( id < 0xffffU ) ;
37 addWord( id ) ; // ID=id - arbitrary identifier to link query with response
38 addByte( 0x01U ) ; // flags - QR=0 (ie. query) and RD=1 (ie. recursion desired)
39 addByte( 0x00U ) ; // RA=0 (recursion available) and Z=0 (zero bits, but see RFC-2671) and RCODE=0 (response code)
40 addWord( 1U ) ; // QDCOUNT=1 (ie. one question section)
41 addWord( 0U ) ; // ANCOUNT=0 (ie. no answer sections)
42 addWord( 0U ) ; // NSCOUNT=0 (ie. no authority sections)
43 addWord( 0U ) ; // ARCOUNT=0 (ie. no additional sections)
44
45 // question section
46 addDomainName( hostname , '.' ) ; // QNAME
47 addWord( DnsMessageRecordType::value(type) ) ; // eg. QTYPE=A
48 addWord( 1U ) ; // QCLASS=IN(ternet)
49}
50
51 void GNet::DnsMessageRequest::addDomainName( const std::string & domain , char sep )
52{
53 std::string_view domain_sv( domain ) ;
54 for( G::StringFieldView part( domain_sv , sep ) ; part ; ++part )
55 {
56 addLabel( part() ) ;
57 }
58 addLabel( std::string_view() ) ; // zero-length root
59}
60
61 void GNet::DnsMessageRequest::addLabel( std::string_view data )
62{
63 if( data.size() > 63U ) throw DnsMessage::Error("overflow") ;
64 addByte( static_cast<unsigned int>(data.size()) ) ;
65 if( !data.empty() )
66 m_data.append( data.data() , data.size() ) ;
67}
68
69 void GNet::DnsMessageRequest::addWord( unsigned int n )
70{
71 addByte( (n >> 8) & 0xFFU ) ;
72 addByte( (n >> 0) & 0xFFU ) ;
73}
74
75 void GNet::DnsMessageRequest::addByte( unsigned int n )
76{
77 m_data.append( 1U , static_cast<char>(static_cast<unsigned char>(n)) ) ;
78}
79
80 const char * GNet::DnsMessageRequest::p() const
81{
82 return m_data.data() ;
83}
84
85std::size_t GNet::DnsMessageRequest::n() const
86{
87 return m_data.size() ;
88}
89
90// ==
91
92GNet::DnsMessage::DnsMessage()
93= default;
94
95 GNet::DnsMessage::DnsMessage( const std::vector<char> & buffer ) :
96 m_buffer(buffer)
97{
98}
99
100 GNet::DnsMessage::DnsMessage( const char * p , std::size_t n ) :
101 m_buffer(p,p+n)
102{
103}
104
105 bool GNet::DnsMessage::valid() const
106{
107 return m_buffer.size() >= 12U && !TC() ;
108}
109
110 const char * GNet::DnsMessage::p() const noexcept
111{
112 return m_buffer.data() ;
113}
114
115std::size_t GNet::DnsMessage::n() const noexcept
116{
117 return m_buffer.size() ;
118}
119
120#ifndef G_LIB_SMALL
121 GNet::DnsMessage GNet::DnsMessage::empty()
122{
123 return {} ;
124}
125#endif
126
127 GNet::DnsMessage GNet::DnsMessage::request( const std::string & type , const std::string & hostname , unsigned int id )
128{
129 DnsMessageRequest r( type , hostname , id ) ;
130 return { r.p() , r.n() } ;
131}
132
133std::vector<GNet::Address> GNet::DnsMessage::addresses() const
134{
135 std::vector<Address> list ;
136 for( unsigned int i = QDCOUNT() ; i < (QDCOUNT()+ANCOUNT()) ; i++ )
137 {
138 list.push_back( rrAddress(i) ) ;
139 }
140 return list ;
141}
142
143 unsigned int GNet::DnsMessage::byte( unsigned int i ) const
144{
145 if( i > m_buffer.size() )
146 throw Error( "invalid offset: " + std::to_string(i) + "/" + std::to_string(m_buffer.size()) ) ;
147 char c = m_buffer.at( i ) ;
148 return static_cast<unsigned char>(c) ;
149}
150
151 unsigned int GNet::DnsMessage::word( unsigned int i ) const
152{
153 return byte(i) * 256U + byte(i+1U) ;
154}
155
156std::string GNet::DnsMessage::span( unsigned int begin , unsigned int end ) const
157{
158 if( begin >= m_buffer.size() || end > m_buffer.size() || begin > end )
159 throw Error( "invalid span" ) ;
160 return { m_buffer.begin()+begin , m_buffer.begin()+end } ;
161}
162
163 unsigned int GNet::DnsMessage::ID() const
164{
165 return word( 0U ) ;
166}
167
168 bool GNet::DnsMessage::QR() const
169{
170 return !!( byte(2U) & 0x80 ) ;
171}
172
173 unsigned int GNet::DnsMessage::OPCODE() const
174{
175 return ( byte(2U) & 0x78 ) >> 3U ;
176}
177
178 bool GNet::DnsMessage::AA() const
179{
180 return !!( byte(2U) & 0x04 ) ;
181}
182
183 bool GNet::DnsMessage::TC() const
184{
185 return !!( byte(2U) & 0x02 ) ;
186}
187
188#ifndef G_LIB_SMALL
189 bool GNet::DnsMessage::RD() const
190{
191 return !!( byte(2U) & 0x01 ) ;
192}
193#endif
194
195#ifndef G_LIB_SMALL
196 bool GNet::DnsMessage::RA() const
197{
198 return !!( byte(3U) & 0x80 ) ;
199}
200#endif
201
202#ifndef G_LIB_SMALL
203 unsigned int GNet::DnsMessage::Z() const
204{
205 return ( byte(3U) & 0x70 ) >> 4 ;
206}
207#endif
208
209 unsigned int GNet::DnsMessage::RCODE() const
210{
211 return byte(3U) & 0x0f ;
212}
213
214 unsigned int GNet::DnsMessage::QDCOUNT() const
215{
216 return word(4U) ;
217}
218
219 unsigned int GNet::DnsMessage::ANCOUNT() const
220{
221 return word(6U) ;
222}
223
224#ifndef G_LIB_SMALL
225 unsigned int GNet::DnsMessage::NSCOUNT() const
226{
227 return word(8U) ;
228}
229#endif
230
231#ifndef G_LIB_SMALL
232 unsigned int GNet::DnsMessage::ARCOUNT() const
233{
234 return word(10U) ;
235}
236#endif
237
238 GNet::DnsMessage GNet::DnsMessage::rejection( const DnsMessage & message , unsigned int rcode )
239{
240 DnsMessage result( message ) ;
241 result.convertToResponse( rcode , false ) ;
242 return result ;
243}
244
245 void GNet::DnsMessage::convertToResponse( unsigned int rcode , bool authoritative )
246{
247 if( m_buffer.size() < 10U || QDCOUNT() == 0U || OPCODE() != 0U )
248 throw Error( "cannot convert" ) ;
249
250 // fix up the header
251 unsigned char * buffer = reinterpret_cast<unsigned char*>( m_buffer.data() ) ;
252 buffer[2U] |= 0x80U ; // QR
253 if( authoritative ) buffer[2U] |= 0x04U ; // AA
254 buffer[3U] &= 0xf0U ; buffer[3U] |= ( rcode & 0x0fU ) ; // RCODE
255 buffer[6U] = 0U ; buffer[7U] = 0U ; // ANCOUNT
256 buffer[8U] = 0U ; buffer[9U] = 0U ; // NSCOUNT
257 buffer[10U] = 0U ; buffer[11U] = 0U ; // ARCOUNT
258
259 // step over the question(s)
260 unsigned int new_size = 12U ; // HEADER size
261 for( unsigned int i = 0U ; i < QDCOUNT() ; i++ )
262 new_size += Question(*this,new_size).size() ;
263
264 // chop off RRs
265 m_buffer.resize( new_size ) ;
266}
267
268 void GNet::DnsMessage::addWord( unsigned int n )
269{
270 addByte( (n >> 8) & 0xFFU ) ;
271 addByte( (n >> 0) & 0xFFU ) ;
272}
273
274 void GNet::DnsMessage::addByte( unsigned int n )
275{
276 m_buffer.push_back( static_cast<char>(static_cast<unsigned char>(n)) ) ;
277}
278
279 GNet::DnsMessageQuestion GNet::DnsMessage::question( unsigned int record_index ) const
280{
281 if( record_index >= QDCOUNT() )
282 throw Error( "invalid record number" ) ;
283
284 unsigned int offset = 12U ; // HEADER size
285 for( unsigned int i = 0U ; i < record_index ; i++ )
286 offset += Question(*this,offset).size() ;
287 return { *this , offset } ;
288}
289
290 GNet::DnsMessageRR GNet::DnsMessage::rr( unsigned int record_index ) const
291{
292 if( record_index < QDCOUNT() )
293 throw Error( "invalid rr number" ) ; // a question is not a RR
294
295 unsigned int offset = 12U ; // HEADER size
296 for( unsigned int i = 0U ; i < record_index ; i++ )
297 {
298 if( i < QDCOUNT() )
299 offset += Question(*this,offset).size() ;
300 else
301 offset += RR(*this,offset).size() ;
302 }
303 return { *this , offset } ;
304}
305
306 GNet::Address GNet::DnsMessage::rrAddress( unsigned int record_index ) const
307{
308 return rr(record_index).address() ;
309}
310
311// ==
312
313 GNet::DnsMessageQuestion::DnsMessageQuestion( const DnsMessage & msg , unsigned int offset )
314{
315 m_qname = DnsMessageNameParser::read( msg , offset ) ;
316 unsigned int qname_size = DnsMessageNameParser::size( msg , offset ) ;
317 m_qtype = msg.word( offset + qname_size ) ;
318 m_qclass = msg.word( offset + qname_size + 2U ) ;
319 m_size = qname_size + 2U + 2U ; // QNAME + QTYPE + QCLASS
320}
321
322 unsigned int GNet::DnsMessageQuestion::size() const
323{
324 return m_size ;
325}
326
327std::string GNet::DnsMessageQuestion::qname() const
328{
329 return m_qname ;
330}
331
332 unsigned int GNet::DnsMessageQuestion::qtype() const
333{
334 return m_qtype ; // eg. AAAA
335}
336
337#ifndef G_LIB_SMALL
338 unsigned int GNet::DnsMessageQuestion::qclass() const
339{
340 return m_qclass ; // eg. IN
341}
342#endif
343
344// ==
345
346 unsigned int GNet::DnsMessageNameParser::size( const DnsMessage & msg , unsigned int offset_in )
347{
348 unsigned int offset = offset_in ;
349 for(;;)
350 {
351 unsigned int n = msg.byte( offset ) ;
352 if( ( n & 0xC0 ) == 0xC0 ) // compression -- see RFC-1035 4.1.4
353 return offset - offset_in + 2U ;
354 else if( ( n & 0xC0 ) != 0 )
355 throw DnsMessage::Error( "unknown label type" ) ; // "reserved for future use"
356 else if( n == 0U )
357 break ;
358 else
359 offset += (n+1U) ;
360 }
361 return offset - offset_in + 1U ;
362}
363
364std::string GNet::DnsMessageNameParser::read( const DnsMessage & msg , unsigned int offset_in )
365{
366 unsigned int offset = offset_in ;
367 std::string result ;
368 for(;;)
369 {
370 unsigned int n = msg.byte( offset ) ;
371 if( ( n & 0xC0U ) == 0xC0U )
372 {
373 unsigned int m = msg.byte(offset+1U) ;
374 offset = (n&0x3FU)*256U + m ;
375 if( offset > offset_in )
376 throw DnsMessage::Error( "invalid label" ) ;
377 }
378 else if( ( n & 0xC0U ) != 0U )
379 {
380 throw DnsMessage::Error( "unknown label type" ) ; // "reserved for future use"
381 }
382 else if( n == 0U )
383 {
384 break ;
385 }
386 else
387 {
388 if( n > 63U )
389 throw DnsMessage::Error( "name overflow" ) ;
390
391 result.append( result.empty()?0U:1U , '.' ) ;
392 result.append( msg.span(offset+1U,offset+n+1U) ) ;
393 offset += (n+1U) ;
394 }
395 }
396 return result ;
397}
398
399// ==
400
401 GNet::DnsMessageRR::DnsMessageRR( const DnsMessage & msg , unsigned int offset ) :
402 m_msg(msg) ,
403 m_offset(offset)
404{
405 m_name = DnsMessageNameParser::read( msg , offset ) ; // NAME
406 offset += DnsMessageNameParser::size( msg , offset ) ;
407
408 m_type = msg.word( offset ) ; offset += 2U ; // TYPE // NOLINT
409 m_class = msg.word( offset ) ; offset += 2U ; // CLASS // NOLINT
410 offset += 4U ; // TTL
411 m_rdata_size = msg.word( offset ) ; offset += 2U ; // RDLENGTH // NOLINT
412
413 m_rdata_offset = offset ; // NOLINT
414 m_size = offset - m_offset + m_rdata_size ;
415
416 if( m_class != 1U ) // "IN" (internet)
417 throw DnsMessage::Error( "invalid rr class" ) ;
418}
419
420#ifndef G_LIB_SMALL
421 unsigned int GNet::DnsMessageRR::type() const
422{
423 return m_type ;
424}
425#endif
426
427#ifndef G_LIB_SMALL
428 unsigned int GNet::DnsMessageRR::class_() const
429{
430 return m_class ;
431}
432#endif
433
434 bool GNet::DnsMessageRR::isa( std::string_view type_name ) const noexcept
435{
436 return m_type == DnsMessageRecordType::value( type_name , std::nothrow ) ;
437}
438
439 unsigned int GNet::DnsMessageRR::size() const
440{
441 return m_size ;
442}
443
444#ifndef G_LIB_SMALL
445std::string GNet::DnsMessageRR::name() const
446{
447 return m_name ;
448}
449#endif
450
451std::string GNet::DnsMessageRR::rdataDname( unsigned int rdata_offset ) const
452{
453 return DnsMessageNameParser::read( m_msg , m_rdata_offset + rdata_offset ) ;
454}
455
456#ifndef G_LIB_SMALL
457std::string GNet::DnsMessageRR::rdataDname( unsigned int * rdata_offset_p ) const
458{
459 std::string dname = DnsMessageNameParser::read( m_msg , m_rdata_offset + *rdata_offset_p ) ;
460 *rdata_offset_p += DnsMessageNameParser::size( m_msg , m_rdata_offset + *rdata_offset_p ) ;
461 return dname ;
462}
463#endif
464
465#ifndef G_LIB_SMALL
466std::string GNet::DnsMessageRR::rdataSpan( unsigned int rdata_begin ) const
467{
468 return rdataSpan( rdata_begin , rdataSize() ) ;
469}
470#endif
471
472std::string GNet::DnsMessageRR::rdataSpan( unsigned int rdata_begin , unsigned int rdata_end ) const
473{
474 return m_msg.span( m_rdata_offset + rdata_begin , m_rdata_offset + rdata_end ) ;
475}
476
477#ifndef G_LIB_SMALL
478 unsigned int GNet::DnsMessageRR::rdataOffset() const
479{
480 return m_rdata_offset ;
481}
482#endif
483
484 unsigned int GNet::DnsMessageRR::rdataSize() const
485{
486 return m_rdata_size ;
487}
488
489 unsigned int GNet::DnsMessageRR::rdataByte( unsigned int i ) const
490{
491 return m_msg.byte( m_rdata_offset + i ) ;
492}
493
494 unsigned int GNet::DnsMessageRR::rdataWord( unsigned int i ) const
495{
496 return m_msg.word( m_rdata_offset + i ) ;
497}
498
499 GNet::Address GNet::DnsMessageRR::address( unsigned int port , std::nothrow_t ) const
500{
501 bool ok = false ;
502 return addressImp( port , ok ) ;
503}
504
505 GNet::Address GNet::DnsMessageRR::address( unsigned int port ) const
506{
507 bool ok = false ;
508 auto a = addressImp( port , ok ) ;
509 if( !ok )
510 throw DnsMessage::Error( "not an address" ) ;
511 return a ;
512}
513
514 GNet::Address GNet::DnsMessageRR::addressImp( unsigned int port , bool & ok ) const
515{
516 std::ostringstream ss ;
517 if( isa("A") && rdataSize() == 4U )
518 {
519 ss << rdataByte(0U) << "." << rdataByte(1U) << "." << rdataByte(2U) << "." << rdataByte(3U) << ":" << port ;
520 }
521 else if( isa("AAAA") && rdataSize() == 16U )
522 {
523 const char * sep = "" ;
524 for( unsigned int i = 0 ; i < 8U ; i++ , sep = ":" )
525 ss << sep << std::hex << rdataWord(i*2U) ;
526 ss << "." << port ;
527 }
528 ok = Address::validString( ss.str() , Address::NotLocal() ) ;
529 return ok ? Address::parse( ss.str() , Address::NotLocal() ) : Address::defaultAddress() ;
530}
531
532// ==
533
534 namespace GNet
535{
536 namespace DnsMessageRecordTypeImp
537 {
538 struct Pair /// A std::pair-like structure used in GNet::DnsMessage, needed for gcc 4.2.1
539 {
540 unsigned int first ;
541 const char * second ;
542 } ;
543 constexpr std::array<Pair,23U> map = {{
544 { 1 , "A" } , // a host address
545 { 2 , "NS" } , // an authoritative name server
546 { 3 , "MD" } , // a mail destination (Obsolete - use MX)
547 { 4 , "MF" } , // a mail forwarder (Obsolete - use MX)
548 { 5 , "CNAME" } , // the canonical name for an alias
549 { 6 , "SOA" } , // marks the start of a zone of authority
550 { 7 , "MB" } , // a mailbox domain name (EXPERIMENTAL)
551 { 8 , "MG" } , // a mail group member (EXPERIMENTAL)
552 { 9 , "MR" } , // a mail rename domain name (EXPERIMENTAL)
553 { 10 , "NULL_" } , // a null RR (EXPERIMENTAL)
554 { 11 , "WKS" } , // a well known service description
555 { 12 , "PTR" } , // a domain name pointer
556 { 13 , "HINFO" } , // host information
557 { 14 , "MINFO" } , // mailbox or mail list information
558 { 15 , "MX" } , // mail exchange
559 { 16 , "TXT" } , // text strings
560 { 28 , "AAAA" } , // IPv6 -- RFC-3596
561 { 33 , "SRV" } , // service pointer -- RFC-2782
562 { 41 , "OPT" } , // extended options -- EDNS0 -- RFC-2671
563 { 43 , "DS" } , // delegation signer -- DNSSEC -- RFC-4034
564 { 46 , "RRSIG" } , // resource record signature -- DNSSEC -- RFC-4034
565 { 47 , "NSEC" } , // next secure -- DNSSEC -- RFC-4034
566 { 48 , "DNSKEY" } // dns public key -- DNSSEC -- RFC-4034
567 }} ;
568 }
569}
570
571 unsigned int GNet::DnsMessageRecordType::value( std::string_view type_name , std::nothrow_t ) noexcept
572{
573 namespace imp = DnsMessageRecordTypeImp ;
574 for( const auto & item : imp::map )
575 {
576 if( G::Str::match( type_name , item.second ) )
577 return item.first ;
578 }
579 return 0U ;
580}
581
582 unsigned int GNet::DnsMessageRecordType::value( std::string_view type_name )
583{
584 unsigned int v = value( type_name , std::nothrow ) ;
585 if( v == 0U )
586 throw DnsMessage::Error( "invalid rr type name" ) ;
587 return v ;
588}
589
590std::string GNet::DnsMessageRecordType::name( unsigned int type_value )
591{
592 namespace imp = DnsMessageRecordTypeImp ;
593 for( const auto & item : imp::map )
594 {
595 if( item.first == type_value )
596 return item.second ;
597 }
598 throw DnsMessage::Error( "invalid rr type value" ) ;
599}
600
GNet::Address
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:63
GNet::Address::validString
static bool validString(std::string_view display_string, std::string *reason=nullptr)
Returns true if the transport-address display string is valid.
Definition: gaddress.cpp:383
GNet::Address::parse
static Address parse(std::string_view display_string)
Factory function for any address family.
Definition: gaddress.cpp:178
GNet::Address::address
const sockaddr * address() const
Returns the sockaddr address.
Definition: gaddress.cpp:417
GNet::DnsMessageNameParser::size
static unsigned int size(const DnsMessage &msg, unsigned int)
Returns the size of the compressed name at the given offset.
Definition: gdnsmessage.cpp:346
GNet::DnsMessageNameParser::read
static std::string read(const DnsMessage &msg, unsigned int)
Returns the decompressed domain name at the given offset, made up of the labels with dots inbetween.
Definition: gdnsmessage.cpp:364
GNet::DnsMessageQuestion
Represents DNS question record.
Definition: gdnsmessage.h:312
GNet::DnsMessageQuestion::DnsMessageQuestion
DnsMessageQuestion(const DnsMessage &, unsigned int offset)
Constructor.
Definition: gdnsmessage.cpp:313
GNet::DnsMessageQuestion::qtype
unsigned int qtype() const
Returns the question QTYPE value.
Definition: gdnsmessage.cpp:332
GNet::DnsMessageQuestion::qname
std::string qname() const
Returns the question domain name (QNAME).
Definition: gdnsmessage.cpp:327
GNet::DnsMessageQuestion::size
unsigned int size() const
Returns the record size.
Definition: gdnsmessage.cpp:322
GNet::DnsMessageQuestion::qclass
unsigned int qclass() const
Returns the question QCLASS value.
Definition: gdnsmessage.cpp:338
GNet::DnsMessageRRData::offset
unsigned int offset() const
Calls rdataOffset().
GNet::DnsMessageRR
Represents DNS response record.
Definition: gdnsmessage.h:241
GNet::DnsMessageRR::type
unsigned int type() const
Returns the RR TYPE value().
Definition: gdnsmessage.cpp:421
GNet::DnsMessageRR::class_
unsigned int class_() const
Returns the RR CLASS value().
Definition: gdnsmessage.cpp:428
GNet::DnsMessageRR::DnsMessageRR
DnsMessageRR(const DnsMessage &, unsigned int offset)
Constructor from DnsMessage data.
Definition: gdnsmessage.cpp:401
GNet::DnsMessageRR::size
unsigned int size() const
Returns the size of the RR.
Definition: gdnsmessage.cpp:439
GNet::DnsMessageRR::address
Address address(unsigned int port=0U) const
Returns the Address if isa(A) or isa(AAAA).
Definition: gdnsmessage.cpp:505
GNet::DnsMessageRR::isa
bool isa(std::string_view) const noexcept
Returns true if the type() has the given name().
Definition: gdnsmessage.cpp:434
GNet::DnsMessageRR::name
std::string name() const
Returns the RR NAME.
Definition: gdnsmessage.cpp:445
GNet::DnsMessageRecordType::value
static unsigned int value(std::string_view type_name)
Returns the type value for the given type name.
Definition: gdnsmessage.cpp:582
GNet::DnsMessageRecordType::name
static std::string name(unsigned int type_value)
Returns the type name for the given type value.
Definition: gdnsmessage.cpp:590
GNet::DnsMessageRequest
Represents a DNS query message.
Definition: gdnsmessage.h:358
GNet::DnsMessageRequest::n
std::size_t n() const
Returns message size.
Definition: gdnsmessage.cpp:85
GNet::DnsMessageRequest::p
const char * p() const
Returns a pointer to the message data.
Definition: gdnsmessage.cpp:80
GNet::DnsMessageRequest::DnsMessageRequest
DnsMessageRequest(const std::string &type, const std::string &hostname, unsigned int id=0U)
Constructor.
Definition: gdnsmessage.cpp:33
GNet::DnsMessage
A DNS message parser, with static factory functions for message composition.
Definition: gdnsmessage.h:56
GNet::DnsMessage::rrAddress
Address rrAddress(unsigned int n) const
Returns the address in the n'th record.
Definition: gdnsmessage.cpp:306
GNet::DnsMessage::ANCOUNT
unsigned int ANCOUNT() const
Returns the header ANCOUNT field, ie.
Definition: gdnsmessage.cpp:219
GNet::DnsMessage::p
const char * p() const noexcept
Returns the raw data.
Definition: gdnsmessage.cpp:110
GNet::DnsMessage::question
Question question(unsigned int n) const
Returns the n'th record as a Question record.
Definition: gdnsmessage.cpp:279
GNet::DnsMessage::RCODE
unsigned int RCODE() const
Returns the header RCODE.
Definition: gdnsmessage.cpp:209
GNet::DnsMessage::QR
bool QR() const
Returns the header QR (query/response).
Definition: gdnsmessage.cpp:168
GNet::DnsMessage::valid
bool valid() const
Returns true if the message data is big enough for a header and its TC() flag is false.
Definition: gdnsmessage.cpp:105
GNet::DnsMessage::Z
unsigned int Z() const
Returns the header Z value (zero).
Definition: gdnsmessage.cpp:203
GNet::DnsMessage::DnsMessage
DnsMessage(const std::vector< char > &buffer)
Constructor. Check with valid().
Definition: gdnsmessage.cpp:95
GNet::DnsMessage::QDCOUNT
unsigned int QDCOUNT() const
Returns the header QDCOUNT field, ie.
Definition: gdnsmessage.cpp:214
GNet::DnsMessage::NSCOUNT
unsigned int NSCOUNT() const
Returns the header NSCOUNT field, ie.
Definition: gdnsmessage.cpp:225
GNet::DnsMessage::ARCOUNT
unsigned int ARCOUNT() const
Returns the header ARCOUNT field, ie.
Definition: gdnsmessage.cpp:232
GNet::DnsMessage::AA
bool AA() const
Returns the header AA flag (authorative).
Definition: gdnsmessage.cpp:178
GNet::DnsMessage::OPCODE
unsigned int OPCODE() const
Returns the header OPCODE.
Definition: gdnsmessage.cpp:173
GNet::DnsMessage::rejection
static DnsMessage rejection(const DnsMessage &request, unsigned int rcode)
Factory function for a failure response based on the given request message.
Definition: gdnsmessage.cpp:238
GNet::DnsMessage::TC
bool TC() const
Returns the header TC flag (truncated).
Definition: gdnsmessage.cpp:183
GNet::DnsMessage::request
static DnsMessage request(const std::string &type, const std::string &hostname, unsigned int id=0U)
Factory function for a request message of the give type ("A", "AAAA", etc).
Definition: gdnsmessage.cpp:127
GNet::DnsMessage::span
std::string span(unsigned int begin, unsigned int end) const
Returns the data in the given half-open byte range.
Definition: gdnsmessage.cpp:156
GNet::DnsMessage::byte
unsigned int byte(unsigned int byte_index) const
Returns byte at the given offset.
Definition: gdnsmessage.cpp:143
GNet::DnsMessage::addresses
std::vector< Address > addresses() const
Returns the Answer addresses.
Definition: gdnsmessage.cpp:133
GNet::DnsMessage::RD
bool RD() const
Returns the header RD (recursion desired).
Definition: gdnsmessage.cpp:189
GNet::DnsMessage::empty
static DnsMessage empty()
Factory function for an unusable object.
Definition: gdnsmessage.cpp:121
GNet::DnsMessage::ID
unsigned int ID() const
Returns the header ID.
Definition: gdnsmessage.cpp:163
GNet::DnsMessage::RA
bool RA() const
Returns the header RA (recursion available).
Definition: gdnsmessage.cpp:196
GNet::DnsMessage::rr
RR rr(unsigned int n) const
Returns the n'th record as a RR record.
Definition: gdnsmessage.cpp:290
GNet::DnsMessage::word
unsigned int word(unsigned int byte_index) const
Returns word at the given byte offset.
Definition: gdnsmessage.cpp:151
GNet::DnsMessage::n
std::size_t n() const noexcept
Returns the raw data size.
Definition: gdnsmessage.cpp:115
G::Str::match
static bool match(std::string_view, std::string_view) noexcept
Returns true if the two strings are the same.
Definition: gstr.cpp:1392
G::StringFieldT
A zero-copy string field iterator where the field separators are short fixed strings.
Definition: gstringfield.h:53
gassert.h
gdnsmessage.h
gstr.h
gstringfield.h
gstringview.h
GNet
Network classes.
Definition: gdef.h:1243
G::hostname
std::string hostname()
Returns the hostname.
Definition: ghostname_unix.cpp:27