E-MailRelay
gdnsblock.h
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 gdnsblock.h
19///
20
21#ifndef G_NET_DNS_BLOCK_H
22#define G_NET_DNS_BLOCK_H
23
24#include "gdef.h"
25#include "gaddress.h"
26#include "gdatetime.h"
27#include "geventhandler.h"
28#include "geventstate.h"
29#include "gexception.h"
30#include "gstringarray.h"
31#include "gtimer.h"
32#include "gsocket.h"
33#include "gstringview.h"
34#include <memory>
35#include <vector>
36
37namespace GNet
38{
39 class DnsBlock ;
40 class DnsBlockResult ;
41 class DnsBlockServerResult ;
42 class DnsBlockCallback ;
43}
44
45//| \class GNet::DnsBlockServerResult
46/// A result structure for one DNSBL server.
47///
49{
50public:
51 explicit DnsBlockServerResult( const std::string & server ) ;
52 ///< Constructor.
53
54 void set( const std::vector<Address> & ) ;
55 ///< Sets the result list().
56
57 bool valid() const ;
58 ///< Returns true if the list() is valid.
59
60 std::string server() const ;
61 ///< Returns the server.
62
63 const std::vector<Address> & addresses() const ;
64 ///< Returns the result list, which is empty if
65 ///< there is no block or not valid().
66
67private:
68 std::string m_server ;
69 bool m_valid {false} ;
70 std::vector<Address> m_addresses ;
71} ;
72
73//| \class GNet::DnsBlockResult
74/// A result structure for GNet::DnsBlock, as delivered by the
75/// DnsBlockCallback interface. The principal attribute is the
76/// type(), which indicates whether the connection should be
77/// allowed or denied.
78///
80{
81public:
82 enum class Type
83 {
84 Inactive , // no configured servers
85 Local , // local address not checked
86 TimeoutAllow , // not all responses in the timeout period
87 TimeoutDeny , // not enough responses in the timeout period
88 Allow , // below threshold of deny responses
89 Deny // threshold of deny responses
90 } ;
91
92public:
94 ///< Constructor.
95
96 void reset( std::size_t threshold , const Address & ) ;
97 ///< Initialiser.
98
99 void add( const DnsBlockServerResult & ) ;
100 ///< Appends the server result.
101
102 DnsBlockServerResult & at( std::size_t ) ;
103 ///< Returns a reference to the given per-server result.
104
105 Type & type() ;
106 ///< Returns a settable reference to the overall result type.
107
108 void log() const ;
109 ///< Logs the results.
110
111 void warn() const ;
112 ///< Emits warnings.
113
114 bool allow() const ;
115 ///< Returns true if the type is Inactive, Local, TimeoutAllow or Allow.
116
117 bool deny() const ;
118 ///< Returns true if the type is TimeoutDeny or Deny.
119
120 const std::vector<DnsBlockServerResult> & list() const ;
121 ///< Returns a reference to the per-server results.
122
123 G::StringArray deniers() const ;
124 ///< Returns the list of denying servers.
125
126 G::StringArray laggards() const ;
127 ///< Returns the list of slow or unresponsive servers.
128
129private:
130 using ResultList = std::vector<DnsBlockServerResult> ;
131 Type m_type {Type::Inactive} ;
132 std::size_t m_threshold {0U} ;
133 Address m_address ;
134 ResultList m_list ;
135} ;
136
137//| \class GNet::DnsBlock
138/// Implements DNS blocklisting, as per RFC-5782. The implementation
139/// sends DNS requests for each configured block-list server
140/// incorporating the IP address to be tested, for example
141/// "1.0.168.192.nospam.com". All requests go to the same DNS
142/// server and are cached or routed in the normal way, so the
143/// block-list servers are not contacted directly.
144///
146{
147public:
148 G_EXCEPTION( Error , tx("dnsbl error") )
149 G_EXCEPTION( ConfigError , tx("invalid dnsbl configuration") )
150 G_EXCEPTION( BadFieldCount , tx("not enough comma-sparated fields") )
151 G_EXCEPTION( SendError , tx("socket send failed") )
152 G_EXCEPTION( BadDnsResponse , tx("invalid dns response") )
153 using ResultList = std::vector<DnsBlockServerResult> ;
154
155 DnsBlock( DnsBlockCallback & , EventState , std::string_view config = {} ) ;
156 ///< Constructor. Use configure() if necessary and then start(),
157 ///< one time only.
158
159 void configure( const Address & dns_server , unsigned int threshold ,
160 bool allow_on_timeout , G::TimeInterval timeout , const G::StringArray & servers ) ;
161 ///< Configures the object after construction.
162
163 void configure( std::string_view ) ;
164 ///< Configuration overload taking a configuration string containing
165 ///< comma-separated fields of: dns-server-address, timeout-ms,
166 ///< threshold, dnsbl-server-list.
167
168 static void checkConfig( const std::string & ) ;
169 ///< Checks the configure() string, throwing on error.
170
171 void start( const Address & ) ;
172 ///< Starts an asychronous check on the given address. The result
173 ///< is delivered via the callback interface passed to the ctor.
174
175 bool busy() const ;
176 ///< Returns true after start() and before the completion callback.
177
178public:
179 ~DnsBlock() override = default ;
180 DnsBlock( const DnsBlock & ) = delete ;
181 DnsBlock( DnsBlock && ) = delete ;
182 DnsBlock & operator=( const DnsBlock & ) = delete ;
183 DnsBlock & operator=( DnsBlock && ) = delete ;
184
185private: // overrides
186 void readEvent() override ; // Override from GNet::EventHandler.
187
188private:
189 static void configureImp( std::string_view , DnsBlock * ) ;
190 void onTimeout() ;
191 static std::string queryString( const Address & ) ;
192 static std::size_t countResponders( const ResultList & ) ;
193 static std::size_t countDeniers( const ResultList & ) ;
194 static Address nameServerAddress() ;
195 static Address nameServerAddress( const std::string & ) ;
196 static bool isDomain( std::string_view ) noexcept ;
197 static bool isPositive( std::string_view ) noexcept ;
198 static unsigned int ms( std::string_view ) ;
199
200private:
201 DnsBlockCallback & m_callback ;
202 EventState m_es ;
203 Timer<DnsBlock> m_timer ;
204 G::StringArray m_servers ;
205 std::size_t m_threshold {1U} ;
206 bool m_allow_on_timeout {true} ;
207 Address m_dns_server ;
208 G::TimeInterval m_timeout {0U} ;
209 DnsBlockResult m_result ;
210 unsigned int m_id_base {0U} ;
211 std::unique_ptr<DatagramSocket> m_socket_ptr ;
212} ;
213
214//| \class GNet::DnsBlockCallback
215/// A callback interface for GNet::DnsBlock.
216///
218{
219public:
220 virtual ~DnsBlockCallback() = default ;
221 ///< Destructor.
222
223 virtual void onDnsBlockResult( const DnsBlockResult & ) = 0 ;
224 ///< Called with the results from DnsBlock::start().
225} ;
226
227// ==
228
229inline
231 m_server(server)
232{
233}
234
235inline
236void GNet::DnsBlockServerResult::set( const std::vector<Address> & addresses )
237{
238 m_valid = true ;
239 m_addresses = addresses ;
240}
241
242inline
244{
245 return m_valid ;
246}
247
248inline
250{
251 return m_server ;
252}
253
254inline
255const std::vector<GNet::Address> & GNet::DnsBlockServerResult::addresses() const
256{
257 return m_addresses ;
258}
259
260inline
262 m_address(Address::defaultAddress())
263{
264}
265
266inline
267void GNet::DnsBlockResult::reset( std::size_t threshold , const Address & address )
268{
269 m_threshold = threshold ;
270 m_address = address ;
271}
272
273inline
274GNet::DnsBlockResult::Type & GNet::DnsBlockResult::type()
275{
276 return m_type ;
277}
278
279inline
280const std::vector<GNet::DnsBlockServerResult> & GNet::DnsBlockResult::list() const
281{
282 return m_list ;
283}
284
285inline
287{
288 m_list.push_back( server_result ) ;
289}
290
291inline
293{
294 return m_list.at( i ) ;
295}
296
297#endif
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:63
A callback interface for GNet::DnsBlock.
Definition: gdnsblock.h:218
virtual void onDnsBlockResult(const DnsBlockResult &)=0
Called with the results from DnsBlock::start().
virtual ~DnsBlockCallback()=default
Destructor.
A result structure for GNet::DnsBlock, as delivered by the DnsBlockCallback interface.
Definition: gdnsblock.h:80
void add(const DnsBlockServerResult &)
Appends the server result.
Definition: gdnsblock.h:286
void warn() const
Emits warnings.
Definition: gdnsblock.cpp:330
bool allow() const
Returns true if the type is Inactive, Local, TimeoutAllow or Allow.
Definition: gdnsblock.cpp:346
G::StringArray laggards() const
Returns the list of slow or unresponsive servers.
Definition: gdnsblock.cpp:376
void reset(std::size_t threshold, const Address &)
Initialiser.
Definition: gdnsblock.h:267
Type & type()
Returns a settable reference to the overall result type.
Definition: gdnsblock.h:274
DnsBlockServerResult & at(std::size_t)
Returns a reference to the given per-server result.
Definition: gdnsblock.h:292
DnsBlockResult()
Constructor.
Definition: gdnsblock.h:261
const std::vector< DnsBlockServerResult > & list() const
Returns a reference to the per-server results.
Definition: gdnsblock.h:280
G::StringArray deniers() const
Returns the list of denying servers.
Definition: gdnsblock.cpp:370
void log() const
Logs the results.
Definition: gdnsblock.cpp:306
bool deny() const
Returns true if the type is TimeoutDeny or Deny.
Definition: gdnsblock.cpp:352
A result structure for one DNSBL server.
Definition: gdnsblock.h:49
bool valid() const
Returns true if the list() is valid.
Definition: gdnsblock.h:243
const std::vector< Address > & addresses() const
Returns the result list, which is empty if there is no block or not valid().
Definition: gdnsblock.h:255
std::string server() const
Returns the server.
Definition: gdnsblock.h:249
DnsBlockServerResult(const std::string &server)
Constructor.
Definition: gdnsblock.h:230
void set(const std::vector< Address > &)
Sets the result list().
Definition: gdnsblock.h:236
Implements DNS blocklisting, as per RFC-5782.
Definition: gdnsblock.h:146
static void checkConfig(const std::string &)
Checks the configure() string, throwing on error.
Definition: gdnsblock.cpp:79
void start(const Address &)
Starts an asychronous check on the given address.
Definition: gdnsblock.cpp:188
void configure(const Address &dns_server, unsigned int threshold, bool allow_on_timeout, G::TimeInterval timeout, const G::StringArray &servers)
Configures the object after construction.
Definition: gdnsblock.cpp:145
DnsBlock(DnsBlockCallback &, EventState, std::string_view config={})
Constructor.
Definition: gdnsblock.cpp:69
bool busy() const
Returns true after start() and before the completion callback.
Definition: gdnsblock.cpp:240
A base class for classes that have a file descriptor and handle asynchronous events from the event lo...
Definition: geventhandler.h:48
A lightweight object containing an ExceptionHandler pointer, optional ExceptionSource pointer and opt...
Definition: geventstate.h:131
A static class for getting information about the local machine's network name and address.
Definition: glocal.h:39
A timer class template in which the timeout is delivered to the specified method.
Definition: gtimer.h:141
An interval between two G::SystemTime values or two G::TimerTime values.
Definition: gdatetime.h:305
Network classes.
Definition: gdef.h:1243
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstringarray.h:30
constexpr const char * tx(const char *p) noexcept
A briefer alternative to G::gettext_noop().
Definition: ggettext.h:84