OpenVPN 3 Core Library
Loading...
Searching...
No Matches
protocol.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12#ifndef OPENVPN_TRANSPORT_PROTOCOL_H
13#define OPENVPN_TRANSPORT_PROTOCOL_H
14
15#include <string>
16#include <cstdint> // for std::uint32_t, etc.
17
21#include <openvpn/addr/ip.hpp>
22
23namespace openvpn {
24// A class that encapsulates a transport protocol.
26{
27 public:
28 enum Type
29 {
35 TLSv4, // TLS over IPv4
36 TLSv6, // TLS over IPv6
37 UnixStream, // unix domain socket (stream)
38 UnixDGram, // unix domain socket (datagram)
39 NamedPipe, // named pipe (Windows only)
43 };
44
51
53 : type_(NONE)
54 {
55 }
56 explicit Protocol(const Type t)
57 : type_(t)
58 {
59 }
61 {
62 return type_;
63 }
64
65 bool defined() const
66 {
67 return type_ != NONE;
68 }
69
70 void reset()
71 {
72 type_ = NONE;
73 }
74
75 bool is_udp() const
76 {
77 return type_ == UDP || type_ == UDPv4 || type_ == UDPv6;
78 }
79 bool is_tcp() const
80 {
81 return type_ == TCP || type_ == TCPv4 || type_ == TCPv6;
82 }
83 bool is_tls() const
84 {
85 return type_ == TLS || type_ == TLSv4 || type_ == TLSv6;
86 }
87 bool is_reliable() const
88 {
89 return is_tcp() || is_tls();
90 }
91 bool is_ipv4() const
92 {
93 return type_ == UDPv4 || type_ == TCPv4 || type_ == TLSv4;
94 }
95 bool is_ipv6() const
96 {
97 return type_ == UDPv6 || type_ == TCPv6 || type_ == TLSv6;
98 }
99 bool is_unix() const
100 {
101 return type_ == UnixStream || type_ == UnixDGram;
102 }
103 bool is_named_pipe() const
104 {
105 return type_ == NamedPipe;
106 }
107 bool is_local() const
108 {
109 return is_unix() || is_named_pipe();
110 }
111
112 bool operator==(const Protocol &other) const
113 {
114 return type_ == other.type_;
115 }
116
117 bool operator!=(const Protocol &other) const
118 {
119 return type_ != other.type_;
120 }
121
122 bool transport_match(const Protocol &other) const
123 {
124 return transport_proto() == other.transport_proto();
125 }
126
127 unsigned int extra_transport_bytes() const
128 {
129 return (is_tcp() || is_tls()) ? sizeof(std::uint16_t) : 0;
130 }
131
133 {
134 switch (ip_version)
135 {
136 case IP::Addr::UNSPEC:
137 break;
138 case IP::Addr::V4:
139 if (is_udp())
140 type_ = UDPv4;
141 else if (is_tcp())
142 type_ = TCPv4;
143 else if (is_tls())
144 type_ = TLSv4;
145 break;
146 case IP::Addr::V6:
147 if (is_udp())
148 type_ = UDPv6;
149 else if (is_tcp())
150 type_ = TCPv6;
151 else if (is_tls())
152 type_ = TLSv6;
153 break;
154 }
155 }
156
157 static Protocol parse(const std::string &str,
158 const AllowSuffix allow_suffix,
159 const char *title = nullptr)
160 {
162 if (string::strcasecmp(str, "adaptive") == 0)
163 return ret;
164 ret.type_ = parse_type(str, allow_suffix);
165 if (ret.type_ == NONE)
166 {
167 if (!title)
168 title = "protocol";
169 OPENVPN_THROW_ARG1(option_error, ERR_INVALID_OPTION_VAL, "error parsing " << title << ": " << str);
170 }
171 return ret;
172 }
173
174 static bool is_local_type(const std::string &str)
175 {
176 if (str.empty())
177 return false;
178 if (str[0] != 'u' && str[0] != 'U' // unix fast path
179 && str[0] != 'n' && str[0] != 'N') // named pipe fast path
180 return false;
181 const Type type = parse_type(str, NO_SUFFIX);
182 return type == UnixStream || type == UnixDGram || type == NamedPipe;
183 }
184
185 int transport_proto() const
186 {
187 switch (type_)
188 {
189 case UDP:
190 case UDPv4:
191 case UDPv6:
192 return 0;
193 case TCP:
194 case TCPv4:
195 case TCPv6:
196 return 1;
197 case UnixDGram:
198 return 2;
199 case UnixStream:
200 return 3;
201 case NamedPipe:
202 return 4;
203 case TLS:
204 case TLSv4:
205 case TLSv6:
206 return 5;
207 default:
208 return -1;
209 }
210 }
211
212 const char *str() const
213 {
214 switch (type_)
215 {
216 case UDP:
217 return "UDP";
218 case UDPv4:
219 return "UDPv4";
220 case UDPv6:
221 return "UDPv6";
222 case TCP:
223 return "TCP";
224 case TCPv4:
225 return "TCPv4";
226 case TCPv6:
227 return "TCPv6";
228 case TLS:
229 return "TLS/TCP";
230 case TLSv4:
231 return "TLS/TCPv4";
232 case TLSv6:
233 return "TLS/TCPv6";
234 case UnixStream:
235 return "UnixStream";
236 case UnixDGram:
237 return "UnixDGram";
238 case NamedPipe:
239 return "NamedPipe";
240 default:
241 return "UNDEF_PROTO";
242 }
243 }
244
245 /* This function returns a parseable string representation of the used
246 * transport protocol. NOTE: returns nullptr if there is no mapping */
247 const char *protocol_to_string() const
248 {
249 switch (type_)
250 {
251 case UDP:
252 return "udp";
253 case UDPv4:
254 return "udp4";
255 case UDPv6:
256 return "udp6";
257 case TCP:
258 return "tcp";
259 case TCPv4:
260 return "tcp4";
261 case TCPv6:
262 return "tcp6";
263 case TLS:
264 return "tls";
265 case TLSv4:
266 return "tls4";
267 case TLSv6:
268 return "tls6";
269 case UnixStream:
270 return "unix-stream";
271 case UnixDGram:
272 return "unix-dgram";
273 case NamedPipe:
274 return "named-pipe";
275 case NONE:
276 return "adaptive";
277 default:
278 return nullptr;
279 }
280 }
281
282 // OpenVPN has always sent UDPv4, TCPv4_* over the wire.
283 // Keep all strings v4 for backward compatibility.
284 const char *occ_str(const bool server) const
285 {
286 switch (type_)
287 {
288 case UDP:
289 case UDPv4:
290 case UDPv6:
291 return "UDPv4";
292 case TCP:
293 case TCPv4:
294 case TCPv6:
295 return server ? "TCPv4_SERVER" : "TCPv4_CLIENT";
296 case TLS:
297 case TLSv4:
298 case TLSv6:
299 return "TLSv4";
300 default:
301 return "UNDEF_PROTO";
302 }
303 }
304
305 private:
306 static Type parse_type(const std::string &str,
307 const AllowSuffix allow_suffix)
308 {
309 Type ret = NONE;
310 std::string s = str;
312 switch (allow_suffix)
313 {
314 case NO_SUFFIX:
315 break;
316 case CLIENT_SUFFIX:
317 if (string::ends_with(s, "-client"))
318 s = s.substr(0, s.length() - 7);
319 break;
320 case SERVER_SUFFIX:
321 if (string::ends_with(s, "-server"))
322 s = s.substr(0, s.length() - 7);
323 break;
324 }
325 if (string::starts_with(s, "unix")) // unix domain socket
326 {
327 if (s == "unix-stream")
328 ret = UnixStream;
329 else if (s == "unix-dgram")
330 ret = UnixDGram;
331 }
332 else if (s == "named-pipe") // Windows named pipe
333 ret = NamedPipe;
334 else if (s.length() >= 3) // udp/tcp/tls
335 {
336 const std::string s1 = s.substr(0, 3);
337 const std::string s2 = s.substr(3);
338 if (s2 == "")
339 {
340 if (s1 == "udp")
341 ret = UDP;
342 else if (s1 == "tcp")
343 ret = TCP;
344 else if (s1 == "tls")
345 ret = TLS;
346 }
347 else if (s2 == "4" || s2 == "v4")
348 {
349 if (s1 == "udp")
350 ret = UDPv4;
351 else if (s1 == "tcp")
352 ret = TCPv4;
353 else if (s1 == "tls")
354 ret = TLSv4;
355 }
356 else if (s2 == "6" || s2 == "v6")
357 {
358 if (s1 == "udp")
359 ret = UDPv6;
360 else if (s1 == "tcp")
361 ret = TCPv6;
362 else if (s1 == "tls")
363 ret = TLSv6;
364 }
365 }
366 return ret;
367 }
368
370};
371} // namespace openvpn
372
373#endif // OPENVPN_TRANSPORT_PROTOCOL_H
bool operator==(const Protocol &other) const
Definition protocol.hpp:112
Type operator()() const
Definition protocol.hpp:60
bool is_unix() const
Definition protocol.hpp:99
const char * protocol_to_string() const
Definition protocol.hpp:247
static Type parse_type(const std::string &str, const AllowSuffix allow_suffix)
Definition protocol.hpp:306
const char * str() const
Definition protocol.hpp:212
const char * occ_str(const bool server) const
Definition protocol.hpp:284
bool operator!=(const Protocol &other) const
Definition protocol.hpp:117
bool is_udp() const
Definition protocol.hpp:75
unsigned int extra_transport_bytes() const
Definition protocol.hpp:127
bool defined() const
Definition protocol.hpp:65
static bool is_local_type(const std::string &str)
Definition protocol.hpp:174
bool is_named_pipe() const
Definition protocol.hpp:103
bool is_ipv4() const
Definition protocol.hpp:91
bool is_local() const
Definition protocol.hpp:107
void mod_addr_version(const IP::Addr::Version ip_version)
Definition protocol.hpp:132
bool is_tls() const
Definition protocol.hpp:83
int transport_proto() const
Definition protocol.hpp:185
bool is_reliable() const
Definition protocol.hpp:87
Protocol(const Type t)
Definition protocol.hpp:56
static Protocol parse(const std::string &str, const AllowSuffix allow_suffix, const char *title=nullptr)
Definition protocol.hpp:157
bool is_tcp() const
Definition protocol.hpp:79
bool transport_match(const Protocol &other) const
Definition protocol.hpp:122
bool is_ipv6() const
Definition protocol.hpp:95
#define OPENVPN_THROW_ARG1(exc, arg, stuff)
int strcasecmp(const char *s1, const char *s2)
Definition string.hpp:29
void to_lower(std::string &str)
Definition string.hpp:607
bool starts_with(const STRING &str, const std::string &prefix)
Definition string.hpp:79
bool ends_with(const STRING &str, const std::string &suffix)
Definition string.hpp:111
const auto ip_version
std::string ret