E-MailRelay

gaddresslocal_unix.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2021 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 gaddresslocal_unix.cpp
19///
20
21#include "gdef.h"
22#include "gaddresslocal.h"
23#include "gstr.h"
24#include "gassert.h"
25#include <cstddef> // offsetof
26#include <cstring> // std::memcpy()
27#include <sys/types.h>
28#include <sys/un.h>
29
30 namespace GNet
31{
32 namespace AddressLocalImp
33 {
34 static constexpr std::size_t minsize()
35 {
36 return sizeof( sockaddr_un::sun_family ) ;
37 }
38 static constexpr std::size_t psize()
39 {
40 return sizeof( sockaddr_un::sun_path ) ;
41 }
42 static std::size_t poffset() noexcept
43 {
44 return offsetof( sockaddr_un , sun_path ) ;
45 }
46 std::string unescape( std::string path )
47 {
48 if( path.size() > 1U && path[0U] == '\\' && path[1U] == '0' )
49 {
50 path = path.substr( 1U ) ;
51 path[0] = '\0' ;
52 }
53 return path ;
54 }
55 }
56}
57
58 unsigned short GNet::AddressLocal::af() noexcept
59{
60 return AF_UNIX ;
61}
62
63 int GNet::AddressLocal::domain() noexcept
64{
65 return PF_UNIX ;
66}
67
68GNet::AddressLocal::AddressLocal( std::nullptr_t ) :
69 m_local{} ,
70 m_size(AddressLocalImp::minsize())
71{
72 m_local.sun_family = af() ;
73 std::memset( m_local.sun_path , 0 , AddressLocalImp::psize() ) ;
74}
75
76GNet::AddressLocal::AddressLocal( unsigned int /*port*/ ) :
77 AddressLocal(nullptr)
78{
79}
80
81GNet::AddressLocal::AddressLocal( unsigned int /*port*/ , int /*loopback_overload*/ ) :
82 AddressLocal(nullptr)
83{
84}
85
86GNet::AddressLocal::AddressLocal( const sockaddr * addr , socklen_t len , bool /*ipv6_scope_id_fixup*/ ) :
87 AddressLocal(nullptr)
88{
89 std::size_t size = static_cast<std::size_t>( len ) ;
90
91 if( addr == nullptr )
92 throw Address::Error() ;
93 if( addr->sa_family != af() || size > sizeof(sockaddr_type) )
94 throw Address::BadFamily() ;
95
96 m_local = *(reinterpret_cast<const sockaddr_type*>(addr)) ;
97 m_size = size ;
98}
99
100GNet::AddressLocal::AddressLocal( const std::string & host_part , unsigned int /*port*/ ) :
101 AddressLocal(nullptr)
102{
103 if( host_part.size() >= AddressLocalImp::psize() )
104 throw Address::BadString( "local-domain address too long" ) ;
105 std::memcpy( m_local.sun_path , host_part.data() , host_part.size() ) ;
106 m_size = AddressLocalImp::poffset() + host_part.size() + 1U ; // include terminator
107}
108
109GNet::AddressLocal::AddressLocal( const std::string & host_part , const std::string & /*port_part*/ ) :
110 AddressLocal(host_part,0)
111{
112}
113
114GNet::AddressLocal::AddressLocal( const std::string & display_string ) :
115 AddressLocal(AddressLocalImp::unescape(display_string),0)
116{
117}
118
119 void GNet::AddressLocal::setPort( unsigned int /*port*/ )
120{
121}
122
123 bool GNet::AddressLocal::setZone( const std::string & /*ipv6_zone_name_or_scope_id*/ )
124{
125 return true ;
126}
127
128 void GNet::AddressLocal::setScopeId( unsigned long /*ipv6_scope_id*/ )
129{
130}
131
132std::string GNet::AddressLocal::path() const
133{
134 namespace imp = AddressLocalImp ;
135 G_ASSERT( m_size >= imp::minsize() ) ;
136 if( m_size <= imp::poffset() )
137 return {} ;
138 else if( m_local.sun_path[0] == '\0' ) // if abstract
139 return { m_local.sun_path , std::min(m_size-imp::poffset(),imp::psize()) } ;
140 else
141 return { m_local.sun_path , std::min(std::strlen(m_local.sun_path),imp::psize()) } ;
142
143}
144
145std::string GNet::AddressLocal::displayString( bool /*ipv6_with_scope*/ ) const
146{
147 std::string p = path() ;
148 return p.empty() ? std::string(1U,'/') : G::Str::printable( p ) ;
149}
150
151std::string GNet::AddressLocal::hostPartString( bool raw ) const
152{
153 return raw ? path() : G::Str::printable(path()) ;
154}
155
156std::string GNet::AddressLocal::queryString() const
157{
158 return {} ;
159}
160
161 bool GNet::AddressLocal::validData( const sockaddr * addr , socklen_t len )
162{
163 return addr != nullptr && addr->sa_family == af() && len >= AddressLocalImp::minsize() && len <= sizeof(sockaddr_type) ;
164}
165
166 bool GNet::AddressLocal::validString( const std::string & path , std::string * reason_p )
167{
168 const char * reason = nullptr ;
169 if( path.size() > AddressLocalImp::psize() )
170 reason = "local-domain address too long" ;
171 if( path.empty() )
172 reason = "empty string" ;
173 if( path[0] != '\0' && path[0] != '/' )
174 reason = "not an absolute filesystem path" ;
175 if( reason && reason_p )
176 *reason_p = std::string( reason ) ;
177 return reason == nullptr ;
178}
179
180 bool GNet::AddressLocal::validStrings( const std::string & host_part , const std::string & /*port_part*/ ,
181 std::string * reason_p )
182{
183 return validString( host_part , reason_p ) ;
184}
185
186 bool GNet::AddressLocal::validPort( unsigned int /*port*/ )
187{
188 return true ;
189}
190
191 bool GNet::AddressLocal::same( const AddressLocal & other , bool /*ipv6_compare_with_scope*/ ) const
192{
193 G_ASSERT( m_local.sun_family == af() ) ;
194 return
195 m_local.sun_family == other.m_local.sun_family &&
196 m_size == other.m_size &&
197 path() == other.path() ;
198}
199
200 bool GNet::AddressLocal::sameHostPart( const AddressLocal & other ) const
201{
202 return same( other ) ;
203}
204
205 unsigned int GNet::AddressLocal::port() const
206{
207 return 0U ;
208}
209
210 unsigned long GNet::AddressLocal::scopeId( unsigned long default_ ) const
211{
212 return default_ ;
213}
214
215 const sockaddr * GNet::AddressLocal::address() const
216{
217 return reinterpret_cast<const sockaddr*>(&m_local) ;
218}
219
220sockaddr * GNet::AddressLocal::address()
221{
222 return reinterpret_cast<sockaddr*>(&m_local) ;
223}
224
225socklen_t GNet::AddressLocal::length() const noexcept
226{
227 return m_size ;
228}
229
230 G::StringArray GNet::AddressLocal::wildcards() const
231{
232 return { displayString() } ;
233}
234
235 bool GNet::AddressLocal::format( const std::string & )
236{
237 return true ;
238}
239
240 bool GNet::AddressLocal::isLocal( std::string & ) const
241{
242 return true ;
243}
244
245 bool GNet::AddressLocal::isLoopback() const
246{
247 return false ;
248}
249
250 bool GNet::AddressLocal::isLinkLocal() const
251{
252 return false ;
253}
254
255 bool GNet::AddressLocal::isUniqueLocal() const
256{
257 return true ;
258}
259
260 bool GNet::AddressLocal::isAny() const
261{
262 return path().empty() ;
263}
264
265 unsigned int GNet::AddressLocal::bits() const
266{
267 return 0U ;
268}
269
gaddresslocal.h
gassert.h
gstr.h
GNet
Network classes.
Definition: gdef.h:1115
G
Low-level classes.
Definition: galign.h:28
G::StringArray
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstrings.h:31