E-MailRelay

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gaddress_ipv6.cpp
1 //
2 // Copyright (C) 2001-2018 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 // gaddress_ipv6.cpp
19 //
20
21 #include "gdef.h"
22 #include "gaddress.h"
23 #include "gaddress4.h"
24 #include "gaddress6.h"
25 #include <cstring>
26
27 namespace
28 {
29 static bool is4( const sockaddr * p )
30 {
31 return p && p->sa_family == GNet::Address4::family() ;
32 }
33 static bool is4( const std::string & s )
34 {
35 std::string r ;
36 return GNet::Address4::validString(s,&r) ;
37 }
38 static bool is4( const std::string & s , unsigned int )
39 {
40 std::string r ;
41 return GNet::Address4::validStrings(s,"0",&r) ;
42 }
43 }
44
45 bool GNet::Address::supports( Family )
46 {
47 return true ;
48 }
49
50 GNet::Address GNet::Address::defaultAddress()
51 {
52 return Address( Family::ipv4() , 0U ) ;
53 }
54
55 GNet::Address::Address( Family f , unsigned int port ) :
56 m_4imp( f==Family::ipv4() ? new Address4(port) : nullptr ) ,
57 m_6imp( f!=Family::ipv4() ? new Address6(port) : nullptr )
58 {
59 }
60
61 GNet::Address::Address( const AddressStorage & storage ) :
62 m_4imp( is4(storage.p()) ? new Address4(storage.p(),storage.n()) : nullptr ) ,
63 m_6imp( !is4(storage.p()) ? new Address6(storage.p(),storage.n()) : nullptr )
64 {
65 }
66
67 GNet::Address::Address( const sockaddr * addr , socklen_t len ) :
68 m_4imp( is4(addr) ? new Address4(addr,len) : nullptr ) ,
69 m_6imp( !is4(addr) ? new Address6(addr,len) : nullptr )
70 {
71 }
72
73 GNet::Address::Address( const std::string & s ) :
74 m_4imp( is4(s) ? new Address4(s) : nullptr ) ,
75 m_6imp( !is4(s) ? new Address6(s) : nullptr )
76 {
77 }
78
79 GNet::Address::Address( const std::string & s , unsigned int port ) :
80 m_4imp( is4(s,port) ? new Address4(s,port) : nullptr ) ,
81 m_6imp( !is4(s,port) ? new Address6(s,port) : nullptr )
82 {
83 }
84
85 GNet::Address::Address( const Address & other ) :
86 m_4imp( other.m_4imp ? new Address4(*other.m_4imp) : nullptr ) ,
87 m_6imp( other.m_6imp ? new Address6(*other.m_6imp) : nullptr )
88 {
89 }
90
91 GNet::Address::Address( Family f , unsigned int port , int loopback_overload ) :
92 m_4imp( f==Family::ipv4() ? new Address4(port,loopback_overload) : nullptr ) ,
93 m_6imp( f!=Family::ipv4() ? new Address6(port,loopback_overload) : nullptr )
94 {
95 }
96
97 GNet::Address GNet::Address::loopback( Family f , unsigned int port )
98 {
99 return Address( f , port , 1 ) ;
100 }
101
102 void GNet::Address::operator=( const Address & addr )
103 {
104 Address temp( addr ) ;
105 std::swap( m_4imp , temp.m_4imp ) ;
106 std::swap( m_6imp , temp.m_6imp ) ;
107 }
108
109 GNet::Address::~Address()
110 {
111 delete m_4imp ;
112 delete m_6imp ;
113 }
114
115 void GNet::Address::setPort( unsigned int port )
116 {
117 m_4imp ? m_4imp->setPort(port) : m_6imp->setPort(port) ;
118 }
119
120 bool GNet::Address::isLoopback() const
121 {
122 return
123 ( m_4imp && m_4imp->isLoopback() ) ||
124 ( m_6imp && m_6imp->isLoopback() ) ;
125 }
126
127 bool GNet::Address::isLocal( std::string & reason ) const
128 {
129 return
130 ( m_4imp && m_4imp->isLocal(reason) ) ||
131 ( m_6imp && m_6imp->isLocal(reason) ) ;
132 }
133
134 bool GNet::Address::operator==( const Address & other ) const
135 {
136 return
137 ( m_4imp && other.m_4imp && m_4imp->same(*other.m_4imp) ) ||
138 ( m_6imp && other.m_6imp && m_6imp->same(*other.m_6imp) ) ;
139 }
140
141 bool GNet::Address::operator!=( const Address & other ) const
142 {
143 return !( *this == other ) ;
144 }
145
146 bool GNet::Address::sameHostPart( const Address & other ) const
147 {
148 return
149 ( m_4imp && other.m_4imp && m_4imp->sameHostPart(*other.m_4imp) ) ||
150 ( m_6imp && other.m_6imp && m_6imp->sameHostPart(*other.m_6imp) ) ;
151 }
152
153 std::string GNet::Address::displayString() const
154 {
155 return m_4imp ? m_4imp->displayString() : m_6imp->displayString() ;
156 }
157
158 std::string GNet::Address::hostPartString() const
159 {
160 return m_4imp ? m_4imp->hostPartString() : m_6imp->hostPartString() ;
161 }
162
163 bool GNet::Address::validString( const std::string & s , std::string * reason_p )
164 {
165 return Address4::validString( s , reason_p ) || Address6::validString( s , reason_p ) ;
166 }
167
168 bool GNet::Address::validStrings( const std::string & s1 , const std::string & s2 , std::string * reason_p )
169 {
170 return Address4::validStrings( s1 , s2 , reason_p ) || Address6::validStrings( s1 , s2 , reason_p ) ;
171 }
172
173 sockaddr * GNet::Address::address()
174 {
175 return m_4imp ? m_4imp->address() : m_6imp->address() ;
176 }
177
178 const sockaddr * GNet::Address::address() const
179 {
180 return m_4imp ? m_4imp->address() : m_6imp->address() ;
181 }
182
183 socklen_t GNet::Address::length() const
184 {
185 return m_4imp ? Address4::length() : Address6::length() ;
186 }
187
188 unsigned int GNet::Address::port() const
189 {
190 return m_4imp ? m_4imp->port() : m_6imp->port() ;
191 }
192
193 unsigned long GNet::Address::scopeId( unsigned long default_ ) const
194 {
195 return m_4imp ? default_ : m_6imp->scopeId() ;
196 }
197
198 bool GNet::Address::validPort( unsigned int port )
199 {
200 return Address4::validPort( port ) ;
201 }
202
203 bool GNet::Address::validData( const sockaddr * addr , socklen_t len )
204 {
205 return Address4::validData( addr , len ) || Address6::validData( addr , len ) ;
206 }
207
208 int GNet::Address::domain() const
209 {
210 return m_4imp ? Address4::domain() : Address6::domain() ;
211 }
212
213 GNet::Address::Family GNet::Address::family() const
214 {
215 return m_4imp ? Family::ipv4() : Family::ipv6() ;
216 }
217
218 G::StringArray GNet::Address::wildcards() const
219 {
220 return m_4imp ? m_4imp->wildcards() : m_6imp->wildcards() ;
221 }
222
223 // ===
224
225 /// \class GNet::AddressStorageImp
226 /// A pimple-pattern implementation class used by GNet::AddressStorage.
227 ///
228 class GNet::AddressStorageImp
229 {
230 public:
231 Address6::union_type u ;
232 socklen_t n ;
233 } ;
234
235 // ==
236
237 GNet::AddressStorage::AddressStorage() :
238 m_imp(new AddressStorageImp)
239 {
240 m_imp->n = sizeof(Address6::union_type) ;
241 }
242
243 GNet::AddressStorage::~AddressStorage()
244 {
245 delete m_imp ;
246 }
247
248 sockaddr * GNet::AddressStorage::p1()
249 {
250 return &(m_imp->u.general) ;
251 }
252
253 socklen_t * GNet::AddressStorage::p2()
254 {
255 return &m_imp->n ;
256 }
257
258 const sockaddr * GNet::AddressStorage::p() const
259 {
260 return &m_imp->u.general ;
261 }
262
263 socklen_t GNet::AddressStorage::n() const
264 {
265 return m_imp->n ;
266 }
267
268 // ==
269
270 // fallback implementation for inet_pton() -- see GCONFIG_HAVE_INET_PTON in gdef.h
271 //
272 int GNet::inet_pton_imp( int f , const char * p , void * result )
273 {
274 if( p == nullptr || result == nullptr ) return 0 ; // just in case
275 struct addrinfo ai_hint ;
276 std::memset( &ai_hint , 0 , sizeof(ai_hint) ) ;
277 ai_hint.ai_family = f ;
278 ai_hint.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV ;
279 struct addrinfo * ai_p = nullptr ;
280 int rc = getaddrinfo( p , nullptr , &ai_hint , &ai_p ) ;
281 bool ok = rc == 0 && ai_p != nullptr ;
282 if( ok && ai_p->ai_addr == nullptr ) { freeaddrinfo(ai_p) ; return 1 ; } // just in case
283 if( ok )
284 {
285 struct sockaddr * sa_p = ai_p->ai_addr ;
286 if( ai_p->ai_family == AF_INET )
287 {
288 struct sockaddr_in sa = *reinterpret_cast<struct sockaddr_in*>(sa_p) ;
289 *reinterpret_cast<struct in_addr*>(result) = sa.sin_addr ;
290 }
291 else if( ai_p->ai_family == AF_INET6 )
292 {
293 struct sockaddr_in6 sa = *reinterpret_cast<struct sockaddr_in6*>(sa_p) ;
294 *reinterpret_cast<struct in6_addr*>(result) = sa.sin6_addr ;
295 }
296 else
297 ok = false ;
298 freeaddrinfo( ai_p ) ;
299 }
300 return ok ? 1 : 0 ;
301 }
302
303 #if ! GCONFIG_HAVE_INET_NTOP
304 // fallback implementation for inet_ntop() -- see GCONFIG_HAVE_INET_NTOP in gdef.h
305 const char * GNet::inet_ntop_imp( int f , void * ap , char * buffer , size_t n )
306 {
307 std::string s ;
308 if( f == AF_INET )
309 {
310 std::ostringstream ss ;
311 struct in_addr a = *reinterpret_cast<struct in_addr*>(ap) ;
312 ss << inet_ntoa( a ) ; // ignore warnings - this is not used if inet_ntop is available
313 s = ss.str() ;
314 }
315 else if( f == AF_INET6 )
316 {
317 struct in6_addr a = *reinterpret_cast<struct in6_addr*>(ap) ;
318 std::ostringstream ss ;
319 const char * sep = ":" ;
320 const char * hexmap = "0123456789abcdef" ;
321 for( int i = 0 ; i < 16 ; i++ , sep = *sep ? "" : ":" )
322 {
323 unsigned int n = static_cast<unsigned int>(a.s6_addr[i]) % 256U ;
324 ss << sep << hexmap[(n>>4U)%16U] << hexmap[(n&15U)%16U] ;
325 }
326 ss << ":" ;
327 s = ss.str() ;
328 for( std::string::size_type pos = s.find(":0") ; pos != std::string::npos ; pos = s.find(":0",pos) )
329 {
330 if( s.find(":0:",pos) == std::string::npos )
331 s.erase( pos+1U , 1U ) ;
332 else
333 pos++ ;
334 }
335 std::string run = ":0:0:0:0:0:0:0:0:" ;
336 while( run.length() >= 3U )
337 {
338 std::string::size_type pos = s.find( run ) ;
339 if( pos != std::string::npos )
340 {
341 std::string::size_type r = 2U ;
342 if( pos == 0U ) r++ ;
343 if( (pos + run.length()) == s.length() ) r++ ;
344 s.replace( pos , run.length() , std::string("::::").substr(0U,r) ) ;
345 break ;
346 }
347 run.erase( 0U , 2U ) ;
348 }
349 s.erase( 0U , 1U ) ;
350 s.erase( s.length()-1U , 1U ) ;
351 }
352 else
353 {
354 return nullptr ;
355 }
356 if( n <= s.length() ) return nullptr ;
357 std::strncpy( buffer , s.c_str() , n ) ;
358 return buffer ;
359 }
360 #endif
361
GNet::Address::loopback
static Address loopback(Family, unsigned int port=0U)
Returns a loopback address.
Definition: gaddress_ipv4.cpp:83
GNet::Address::family
Family family() const
Returns the address family.
Definition: gaddress_ipv4.cpp:189
GNet::Address::validData
static bool validData(const sockaddr *, socklen_t len)
Returns true if the sockaddr data is valid.
Definition: gaddress_ipv4.cpp:179
GNet::Address
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:54
GNet::Address::isLoopback
bool isLoopback() const
Returns true if this is a loopback address.
Definition: gaddress_ipv4.cpp:104
GNet::Address::validStrings
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_ipv4.cpp:144
G::StringArray
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstrings.h:33
GNet::AddressStorage::p2
socklen_t * p2()
Returns the length pointer for accept()/getsockname()/getpeername() to write into.
Definition: gaddress_ipv4.cpp:229
GNet::AddressStorage::p1
sockaddr * p1()
Returns the sockaddr pointer for accept()/getsockname()/getpeername() to write into.
Definition: gaddress_ipv4.cpp:224
GNet::AddressStorageImp
A pimple-pattern implementation class used by GNet::AddressStorage.
Definition: gaddress_ipv4.cpp:204
GNet::Address::address
const sockaddr * address() const
Returns the sockaddr address.
Definition: gaddress_ipv4.cpp:154
GNet::Address::sameHostPart
bool sameHostPart(const Address &other) const
Returns true if the two addresses have the same host part (ie.
Definition: gaddress_ipv4.cpp:124
GNet::Address::port
unsigned int port() const
Returns port part of the address.
Definition: gaddress_ipv4.cpp:164
GNet::Address::operator==
bool operator==(const Address &) const
Comparison operator.
Definition: gaddress_ipv4.cpp:114
GNet::AddressStorage::p
const sockaddr * p() const
Returns the pointer.
Definition: gaddress_ipv4.cpp:234
GNet::AddressStorage::AddressStorage
AddressStorage()
Default constructor.
Definition: gaddress_ipv4.cpp:213
GNet::Address::defaultAddress
static Address defaultAddress()
Returns a default address, being the IPv4 wildcard address with a zero port number.
Definition: gaddress_ipv4.cpp:41
GNet::Address::wildcards
G::StringArray wildcards() const
Returns an ordered list of wildcard strings that match this address.
Definition: gaddress_ipv4.cpp:194
GNet::Address::length
socklen_t length() const
Returns the size of the sockaddr address. See address().
Definition: gaddress_ipv4.cpp:159
GNet::Address::hostPartString
std::string hostPartString() const
Returns a string which represents the network address for debugging and diagnostics purposes...
Definition: gaddress_ipv4.cpp:134
GNet::Address::scopeId
unsigned long scopeId(unsigned long default_=0UL) const
Returns the scope-id.
Definition: gaddress_ipv4.cpp:169
GNet::Address::validString
static bool validString(const std::string &display_string, std::string *reason=nullptr)
Returns true if the transport-address display string is valid.
Definition: gaddress_ipv4.cpp:139
GNet::Address::domain
int domain() const
Returns the address 'domain', eg. PF_INET.
Definition: gaddress_ipv4.cpp:184
GNet::Address::~Address
~Address()
Destructor.
Definition: gaddress_ipv4.cpp:94
GNet::AddressStorage::~AddressStorage
~AddressStorage()
Destructor.
Definition: gaddress_ipv4.cpp:219
GNet::Address::validPort
static bool validPort(unsigned int n)
Returns true if the port number is within the valid range.
Definition: gaddress_ipv4.cpp:174
GNet::Address::Family
A type-safe enumerator for IP address family.
Definition: gaddress.h:57
gaddress6.h
This file is formatted for side-by-side comparison with gaddress4.h.
GNet::Address::isLocal
bool isLocal(std::string &reason) const
Returns true if this seems to be a local address (for some definition of 'local').
Definition: gaddress_ipv4.cpp:109
GNet::Address::operator=
void operator=(const Address &addr)
Assignment operator.
Definition: gaddress_ipv4.cpp:88
GNet::Address::Address
Address(const Address &)
Copy constructor.
Definition: gaddress_ipv4.cpp:72
gaddress4.h
This file is formatted for side-by-side comparison with gaddress6.h.
gaddress.h
GNet::Address::setPort
void setPort(unsigned int port)
Sets the port number.
Definition: gaddress_ipv4.cpp:99
GNet::AddressStorage::n
socklen_t n() const
Returns the length.
Definition: gaddress_ipv4.cpp:239
GNet::Address::supports
static bool supports(Family)
Returns true if the implementation supports the given address family.
Definition: gaddress_ipv4.cpp:36
GNet::Address::operator!=
bool operator!=(const Address &) const
Comparison operator.
Definition: gaddress_ipv4.cpp:119
GNet::Address::displayString
std::string displayString() const
Returns a string which represents the transport address for debugging and diagnostics purposes...
Definition: gaddress_ipv4.cpp:129