E-MailRelay
gaddress.h
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2023 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 gaddress.h
19///
20
21#ifndef G_NET_ADDRESS_H
22#define G_NET_ADDRESS_H
23
24#include "gdef.h"
25#include "gstringarray.h"
26#include "gbasicaddress.h"
27#include "gexception.h"
28#include <string>
29#include <memory>
30
31namespace GNet
32{
33 class Address ;
34 class Address4 ;
35 class Address6 ;
36 class AddressLocal ;
37 class AddressStorage ;
38 class AddressStorageImp ;
39}
40
41//| \class GNet::Address
42/// The GNet::Address class encapsulates a TCP/UDP transport address. The
43/// address is exposed as a 'sockaddr' structure for low-level socket
44/// operations.
45///
46/// A multi-pimple pattern is used for the implementation, with implementation
47/// classes including GNet::Address4 and GNet::Address6. In an IPv4-only build
48/// the GNet::Address6 can be forward-declared but not defined, with all methods
49/// forwarded to the GNet::Address4 sub-object.
50///
51/// Unix domain addresses are supported by the GNet::AddressLocal implementation
52/// class. Port numbers are not expected when parsing and port numbers are not
53/// included in the display string. Unix domain addresses are only allowed
54/// to be absolute filesystem paths starting with '/' and with no unprintable
55/// characters, or the well-defined zero-length address (for unbound sockets)
56/// which is given the display string of "/". Paths with funny characters or
57/// linux-specific abstract addresses (see man unix(7)) will throw.
58///
59/// \see GNet::Resolver
60///
62{
63public:
64 enum class Family
65 {
66 ipv4 ,
67 ipv6 ,
68 local
69 } ;
70 struct Domain /// Overload discriminator for Address::supports()
71 {} ;
72
73 G_EXCEPTION( Error , tx("address error") ) ;
74 G_EXCEPTION( BadString , tx("invalid address") ) ;
75 G_EXCEPTION_CLASS( BadFamily , tx("unsupported address family") ) ;
76
77 static bool supports( Family ) noexcept ;
78 ///< Returns true if the implementation supports the given
79 ///< address family.
80
81 static bool supports( int af , int dummy ) noexcept ;
82 ///< Returns true if the implementation supports the given
83 ///< address family given as AF_INET etc.
84
85 static bool supports( const Domain & , int domain ) noexcept ;
86 ///< Returns true if the implementation supports the given
87 ///< address domain given as PF_INET etc.
88
89 Address( const Address & ) ;
90 ///< Copy constructor.
91
92 explicit Address( const AddressStorage & ) ;
93 ///< Constructor taking a storage object.
94
95 Address( const sockaddr * addr , socklen_t len ) ;
96 ///< Constructor using a given sockaddr. Throws an exception if an
97 ///< invalid structure. See also: validData()
98
99 Address( const sockaddr * addr , socklen_t len , bool fixup ) ;
100 ///< An overload that conditionally applies the bsd ipv6 scope-id
101 ///< fixup.
102
103 Address( Family , unsigned int port ) ;
104 ///< Constructor for a wildcard address like INADDR_ANY with the
105 ///< given port number. Throws an exception if an invalid port number.
106 ///< Postcondition: isAny()
107 /// \see validPort()
108
109 Address( Address && ) noexcept ;
110 ///< Move constructor.
111
113 ///< Destructor.
114
115 Address & operator=( const Address & ) ;
116 ///< Assignment operator.
117
118 Address & operator=( Address && ) noexcept ;
119 ///< Move assignment operator.
120
121 operator G::BasicAddress() const ;
122 ///< Returns a G::BasicAddress.
123
124 struct NotLocal /// Overload discriminator for Address::parse()
125 {} ;
126
127 static Address parse( const std::string & display_string ) ;
128 ///< Factory function for any address family. Throws if
129 ///< an invalid string. See also validString().
130
131 static Address parse( const std::string & display_string , NotLocal ) ;
132 ///< Factory function for Family::ipv4 or Family::ipv6.
133 ///< Throws if an invalid string. See also validString().
134
135 static Address parse( const std::string & host_part_string , unsigned int port ) ;
136 ///< Factory function for Family::ipv4 or Family::ipv6.
137 ///< Throws if an invalid string. See also validStrings().
138
139 static Address parse( const std::string & host_part_string , const std::string & port ) ;
140 ///< Factory function for Family::ipv4 or Family::ipv6.
141 ///< Throws if an invalid string. See also validStrings().
142
143 static bool isFamilyLocal( const std::string & display_string ) noexcept ;
144 ///< Returns true if the given address display string looks
145 ///< will parse to Family::local and Family::local is
146 ///< supported. The address may still fail to parse if
147 ///< it is invalid.
148
149 static Address defaultAddress() ;
150 ///< Returns a default address, being the IPv4 wildcard address
151 ///< with a zero port number.
152
153 static Address loopback( Family , unsigned int port = 0U ) ;
154 ///< Returns a loopback address.
155
156 const sockaddr * address() const ;
157 ///< Returns the sockaddr address. Typically used when making socket
158 ///< system calls. Never returns nullptr.
159
160 sockaddr * address() ;
161 ///< This is a non-const version of address() for compiling on systems
162 ///< which are not properly const-clean.
163
164 socklen_t length() const;
165 ///< Returns the size of the sockaddr address. See address().
166
167 std::string displayString( bool with_scope_id = false ) const ;
168 ///< Returns a printable string that represents the transport
169 ///< address.
170
171 std::string hostPartString() const ;
172 ///< Returns a printable string that represents the network
173 ///< address.
174
175 std::string queryString() const ;
176 ///< Returns a string that can be used as a prefix for rDNS or
177 ///< DNSBL queries.
178
179 unsigned int port() const;
180 ///< Returns port part of the address.
181
182 static int domain( Family ) noexcept ;
183 ///< Returns the address 'domain' for the given family, eg. PF_INET
184 ///< for Family::ipv4.
185
186 Family family() const noexcept ;
187 ///< Returns the address family enumeration.
188
189 int af() const noexcept ;
190 ///< Returns the address family number such as AF_INET or AFINET6.
191
192 static bool validPort( unsigned int n ) ;
193 ///< Returns true if the port number is within the valid range. This
194 ///< can be used to avoid exceptions from the relevant constructors.
195
196 static bool validString( const std::string & display_string , std::string * reason = nullptr ) ;
197 ///< Returns true if the transport-address display string is valid.
198 ///< This can be used to avoid exceptions from the relevant constructor.
199
200 static bool validString( const std::string & display_string , NotLocal , std::string * reason = nullptr ) ;
201 ///< Returns true if the transport-address display string is valid.
202 ///< This can be used to avoid exceptions from the relevant constructor.
203
204 static bool validStrings( const std::string & ip , const std::string & port_string , std::string * reason = nullptr ) ;
205 ///< Returns true if the combined network-address string and port string
206 ///< is valid. This can be used to avoid exceptions from the relevant
207 ///< constructor.
208
209 static bool validData( const sockaddr * , socklen_t len ) ;
210 ///< Returns true if the sockaddr data is valid. This can be used
211 ///< to avoid exceptions from the relevant constructor.
212
213 bool sameHostPart( const Address & other ) const ;
214 ///< Returns true if the two addresses have the same host part
215 ///< (ie. the network address, ignoring the port number).
216
217 Address & setPort( unsigned int port ) ;
218 ///< Sets the port number. Throws an exception if an invalid
219 ///< port number (ie. too big).
220
221 bool setZone( const std::string & ) ;
222 ///< Sets the zone. The parameter is normally a decimal string
223 ///< representation of the zone-id, aka scope-id (eg. "1"), but
224 ///< if not numeric then it is treated as an interface name
225 ///< which is mapped to a zone-id by if_nametoindex(3). Returns
226 ///< false on error. Returns true if zones are not used by the
227 ///< address family.
228
229 Address & setScopeId( unsigned long ) ;
230 ///< Sets the scope-id.
231
232 unsigned long scopeId( unsigned long default_ = 0UL ) const ;
233 ///< Returns the scope-id. Returns the default if scope-ids are not
234 ///< supported by the underlying address type.
235
236 G::StringArray wildcards() const ;
237 ///< Returns an ordered list of wildcard strings that match this
238 ///< address. The fully-address-specific string (eg. "192.168.0.1")
239 ///< comes first, and the most general match-all wildcard like
240 ///< "*.*.*.*" or "128.0.0.0/1" comes last.
241
242 unsigned int bits() const ;
243 ///< Returns the number of leading bits set, relevant only
244 ///< to netmask addresses.
245
246 bool isLoopback() const ;
247 ///< Returns true if this is a loopback address.
248
249 bool isLinkLocal() const ;
250 ///< Returns true if this is a link-local address.
251
252 bool isUniqueLocal() const ;
253 ///< Returns true if this is a locally administered address.
254
255 bool isAny() const ;
256 ///< Returns true if this is the address family's 'any' address.
257
258 bool isLocal( std::string & reason ) const ;
259 ///< Returns true if this seems to be a 'local' address, ie. an
260 ///< address that is likely to be more trusted. Returns an
261 ///< explanation by reference otherwise.
262
263 bool isMulticast() const ;
264 ///< Returns true if this is a multicast address.
265
266 bool is4() const noexcept ;
267 ///< Returns true if family() is ipv4.
268
269 bool is6() const noexcept ;
270 ///< Returns true if family() is ipv6.
271
272 bool same( const Address & , bool ipv6_compare_with_scope ) const ;
273 ///< Comparison function.
274
275 bool operator==( const Address & ) const ;
276 ///< Comparison operator.
277
278 bool operator!=( const Address & ) const ;
279 ///< Comparison operator.
280
281 void swap( Address & other ) noexcept ;
282 ///< Swaps this with other.
283
284private:
285 Address( Family , unsigned int , int ) ; // loopback()
286 Address( const std::string & display_string , bool with_local ) ; // parse(), parse(NotLocal)
287 Address( const std::string & ip , const std::string & port ) ; // parse(ip,port)
288 Address( const std::string & ip , unsigned int port ) ; // parse(ip,port)
289
290private:
291 std::unique_ptr<Address4> m_ipv4 ;
292 std::unique_ptr<Address6> m_ipv6 ;
293 std::unique_ptr<AddressLocal> m_local ;
294} ;
295
296namespace GNet
297{
298 inline void swap( Address & a , Address & b ) noexcept
299 {
300 a.swap(b) ;
301 }
302}
303
304//| \class GNet::AddressStorage
305/// A helper class for calling accept(), getsockname() and getpeername()
306/// and hiding the definition of sockaddr_storage.
307///
309{
310public:
312 ///< Default constructor, with n() reflecting the size of the
313 ///< largest supported address type.
314
316 ///< Destructor.
317
318 sockaddr * p1() ;
319 ///< Returns the sockaddr pointer for accept()/getsockname()/getpeername()
320 ///< to write into.
321
322 socklen_t * p2() ;
323 ///< Returns the length pointer for accept()/getsockname()/getpeername()
324 ///< to write into.
325
326 const sockaddr * p() const ;
327 ///< Returns the pointer, typically set via p1().
328
329 socklen_t n() const ;
330 ///< Returns the length, typically modified via p2().
331
332public:
333 AddressStorage( const AddressStorage & ) = delete ;
334 AddressStorage( AddressStorage && ) = delete ;
335 AddressStorage & operator=( const AddressStorage & ) = delete ;
336 AddressStorage & operator=( AddressStorage && ) = delete ;
337
338private:
339 std::unique_ptr<AddressStorageImp> m_imp ;
340} ;
341
342#endif
A 'sockaddr' wrapper class for IPv4 addresses.
Definition: gaddress4.h:37
A 'sockaddr' wrapper class for IPv6 addresses.
Definition: gaddress6.h:37
A 'sockaddr' wrapper class for local-domain addresses.
Definition: gaddresslocal.h:55
A helper class for calling accept(), getsockname() and getpeername() and hiding the definition of soc...
Definition: gaddress.h:309
~AddressStorage()
Destructor.
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:62
bool setZone(const std::string &)
Sets the zone.
Definition: gaddress.cpp:230
Address(Address &&) noexcept
Move constructor.
Address & setScopeId(unsigned long)
Sets the scope-id.
Definition: gaddress.cpp:240
Address(const Address &)
Copy constructor.
Definition: gaddress.cpp:144
bool is6() const noexcept
Returns true if family() is ipv6.
Definition: gaddress.cpp:319
bool isLinkLocal() const
Returns true if this is a link-local address.
Definition: gaddress.cpp:276
static bool isFamilyLocal(const std::string &display_string) noexcept
Returns true if the given address display string looks will parse to Family::local and Family::local ...
Definition: gaddress.cpp:200
int af() const noexcept
Returns the address family number such as AF_INET or AFINET6.
Definition: gaddress.cpp:484
std::string queryString() const
Returns a string that can be used as a prefix for rDNS or DNSBL queries.
Definition: gaddress.cpp:376
G::StringArray wildcards() const
Returns an ordered list of wildcard strings that match this address.
Definition: gaddress.cpp:492
static bool validData(const sockaddr *, socklen_t len)
Returns true if the sockaddr data is valid.
Definition: gaddress.cpp:460
static int domain(Family) noexcept
Returns the address 'domain' for the given family, eg.
Definition: gaddress.cpp:468
static Address loopback(Family, unsigned int port=0U)
Returns a loopback address.
Definition: gaddress.cpp:210
bool is4() const noexcept
Returns true if family() is ipv4.
Definition: gaddress.cpp:314
static bool validPort(unsigned int n)
Returns true if the port number is within the valid range.
Definition: gaddress.cpp:455
bool isUniqueLocal() const
Returns true if this is a locally administered address.
Definition: gaddress.cpp:296
static bool validStrings(const std::string &ip, const std::string &port_string, std::string *reason=nullptr)
Returns true if the combined network-address string and port string is valid.
Definition: gaddress.cpp:400
void swap(Address &other) noexcept
Swaps this with other.
Definition: gaddress.cpp:161
socklen_t length() const
Returns the size of the sockaddr address. See address().
Definition: gaddress.cpp:428
bool isLocal(std::string &reason) const
Returns true if this seems to be a 'local' address, ie.
Definition: gaddress.cpp:267
static Address defaultAddress()
Returns a default address, being the IPv4 wildcard address with a zero port number.
Definition: gaddress.cpp:205
Address & operator=(const Address &)
Assignment operator.
Definition: gaddress.cpp:169
bool isAny() const
Returns true if this is the address family's 'any' address.
Definition: gaddress.cpp:305
static Address parse(const std::string &display_string)
Factory function for any address family.
Definition: gaddress.cpp:178
static bool validString(const std::string &display_string, std::string *reason=nullptr)
Returns true if the transport-address display string is valid.
Definition: gaddress.cpp:385
static bool supports(Family) noexcept
Returns true if the implementation supports the given address family.
Definition: gaddress.cpp:33
bool sameHostPart(const Address &other) const
Returns true if the two addresses have the same host part (ie.
Definition: gaddress.cpp:348
unsigned int bits() const
Returns the number of leading bits set, relevant only to netmask addresses.
Definition: gaddress.cpp:249
std::string displayString(bool with_scope_id=false) const
Returns a printable string that represents the transport address.
Definition: gaddress.cpp:358
unsigned int port() const
Returns port part of the address.
Definition: gaddress.cpp:437
std::string hostPartString() const
Returns a printable string that represents the network address.
Definition: gaddress.cpp:367
bool isMulticast() const
Returns true if this is a multicast address.
Definition: gaddress.cpp:286
bool isLoopback() const
Returns true if this is a loopback address.
Definition: gaddress.cpp:258
const sockaddr * address() const
Returns the sockaddr address.
Definition: gaddress.cpp:419
unsigned long scopeId(unsigned long default_=0UL) const
Returns the scope-id.
Definition: gaddress.cpp:446
Address & setPort(unsigned int port)
Sets the port number.
Definition: gaddress.cpp:220
Family family() const noexcept
Returns the address family enumeration.
Definition: gaddress.cpp:476
bool same(const Address &, bool ipv6_compare_with_scope) const
Comparison function.
Definition: gaddress.cpp:324
Network classes.
Definition: gdef.h:1144
Low-level classes.
Definition: garg.h:30
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstringarray.h:30
constexpr const char * tx(const char *p)
A briefer alternative to G::gettext_noop().
Definition: ggettext.h:84
STL namespace.
Overload discriminator for Address::supports()
Definition: gaddress.h:71
Overload discriminator for Address::parse()
Definition: gaddress.h:125