OpenVPN 3 Core Library
Loading...
Searching...
No Matches
udpcli.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// UDP transport object specialized for client.
13
14#ifndef OPENVPN_TRANSPORT_CLIENT_UDPCLI_H
15#define OPENVPN_TRANSPORT_CLIENT_UDPCLI_H
16
17#include <sstream>
18
19#include <openvpn/io/io.hpp>
20
28
30
32{
33 public:
35
42
44
45#ifdef OPENVPN_GREMLIN
46 Gremlin::Config::Ptr gremlin_config;
47#endif
48
49 static Ptr new_obj()
50 {
51 return new ClientConfig;
52 }
53
54 TransportClient::Ptr new_transport_client_obj(openvpn_io::io_context &io_context,
55 TransportClientParent *parent) override;
56
57 void process_push(const OptionList &opt) override
58 {
60 }
61
62 private:
64 : server_addr_float(false),
66 n_parallel(8),
67 socket_protect(nullptr)
68 {
69 }
70};
71
73{
75
76 friend class ClientConfig; // calls constructor
77 friend class UDPLink<Client *>; // calls udp_read_handler
78
80
81 public:
82 void transport_start() override
83 {
84 if (!impl)
85 {
86 halt = false;
87 if (config->remote_list->endpoint_available(&server_host, &server_port, &server_protocol))
88 {
90 }
91 else
92 {
94
95 if (config->synchronous_dns_lookup)
96 {
97 openvpn_io::error_code error;
98 results_type results = resolver.resolve(server_host, server_port, error);
99 resolve_callback(error, results);
100 }
101 else
102 {
104 }
105 }
106 }
107 }
108
109 bool transport_send_const(const Buffer &buf) override
110 {
111 return send(buf);
112 }
113
114 bool transport_send(BufferAllocated &buf) override
115 {
116 return send(buf);
117 }
118
119 bool transport_send_queue_empty() override // really only has meaning for TCP
120 {
121 return false;
122 }
123
125 {
126 return false;
127 }
128
130 {
131 }
132
134 {
135 return 0;
136 }
137
138 void reset_align_adjust(const size_t align_adjust) override
139 {
140 if (impl)
141 impl->reset_align_adjust(align_adjust);
142 }
143
144 void server_endpoint_info(std::string &host, std::string &port, std::string &proto, std::string &ip_addr) const override
145 {
148 proto = server_protocol.str();
149 const IP::Addr addr = server_endpoint_addr();
150 ip_addr = addr.to_string();
151 }
152
154 {
155 return IP::Addr::from_asio(server_endpoint.address());
156 }
157
158 unsigned short server_endpoint_port() const override
159 {
160 return server_endpoint.port();
161 }
162
163 openvpn_io::detail::socket_type native_handle() override
164 {
165 return socket.native_handle();
166 }
167
169 {
170 return server_protocol;
171 }
172
173 void stop() override
174 {
175 stop_();
176 }
177 ~Client() override
178 {
179 stop_();
180 }
181
182 private:
183 Client(openvpn_io::io_context &io_context_arg,
184 ClientConfig *config_arg,
185 TransportClientParent *parent_arg)
186 : AsyncResolvableUDP(io_context_arg),
187 socket(io_context_arg),
188 config(config_arg),
189 parent(parent_arg),
190 resolver(io_context_arg),
191 halt(false)
192 {
193 }
194
195 void transport_reparent(TransportClientParent *parent_arg) override
196 {
197 parent = parent_arg;
198 }
199
200 bool send(const Buffer &buf)
201 {
202 if (impl)
203 {
204 const int err = impl->send(buf, nullptr);
205 if (unlikely(err))
206 {
207 // While UDP errors are generally ignored, certain
208 // errors should be forwarded up to the higher levels.
209#ifdef OPENVPN_PLATFORM_IPHONE
210 if (err == EADDRNOTAVAIL)
211 {
212 stop();
213 parent->transport_error(Error::TRANSPORT_ERROR, "EADDRNOTAVAIL: Can't assign requested address");
214 }
215#endif
216 return false;
217 }
218 else
219 return true;
220 }
221 else
222 return false;
223 }
224
225 void udp_read_handler(PacketFrom::SPtr &pfp) // called by LinkImpl
226 {
227 if (config->server_addr_float || pfp->sender_endpoint == server_endpoint)
228 parent->transport_recv(pfp->buf);
229 else
230 config->stats->error(Error::BAD_SRC_ADDR);
231 }
232
233 void stop_()
234 {
235 if (!halt)
236 {
237 halt = true;
238 if (impl)
239 impl->stop();
240 socket.close();
241 resolver.cancel();
243 }
244 }
245
246 // called after DNS resolution has succeeded or failed
247 void resolve_callback(const openvpn_io::error_code &error,
248 results_type results) override
249 {
250 if (!halt)
251 {
252 if (!error)
253 {
254 // save resolved endpoint list in remote_list
255 config->remote_list->set_endpoint_range(results);
257 }
258 else
259 {
260 std::ostringstream os;
261 os << "DNS resolve error on '" << server_host << "' for UDP session: " << error.message();
262 config->stats->error(Error::RESOLVE_ERROR);
263 stop();
265 }
266 }
267 }
268
269 // do UDP connect
271 {
272 config->remote_list->get_endpoint(server_endpoint);
273 OPENVPN_LOG("Contacting " << server_endpoint << " via UDP");
275 socket.open(server_endpoint.protocol());
276
277 if (config->socket_protect)
278 {
279 if (!config->socket_protect->socket_protect(socket.native_handle(), server_endpoint_addr()))
280 {
281 config->stats->error(Error::SOCKET_PROTECT_ERROR);
282 stop();
283 parent->transport_error(Error::UNDEF, "socket_protect error (UDP)");
284 return;
285 }
286 }
287
288 socket.async_connect(server_endpoint, [self = Ptr(this)](const openvpn_io::error_code &error)
289 {
291 self->start_impl_(error); });
292 }
293
294 // start I/O on UDP socket
295 void start_impl_(const openvpn_io::error_code &error)
296 {
297 if (!halt)
298 {
299 if (!error)
300 {
301 impl.reset(new LinkImpl(this,
302 socket,
303 (*config->frame)[Frame::READ_LINK_UDP],
304 config->stats));
305#ifdef OPENVPN_GREMLIN
306 impl->gremlin_config(config->gremlin_config);
307#endif
308 impl->start(config->n_parallel);
310 }
311 else
312 {
313 std::ostringstream os;
314 os << "UDP connect error on '" << server_host << ':' << server_port << "' (" << server_endpoint << "): " << error.message();
315 config->stats->error(Error::UDP_CONNECT_ERROR);
316 stop();
318 }
319 }
320 }
321
322 std::string server_host;
323 std::string server_port;
324
326
327 openvpn_io::ip::udp::socket socket;
331 openvpn_io::ip::udp::resolver resolver;
333 bool halt;
334};
335
336inline TransportClient::Ptr ClientConfig::new_transport_client_obj(openvpn_io::io_context &io_context,
337 TransportClientParent *parent)
338{
339 return TransportClient::Ptr(new Client(io_context, this, parent));
340}
341} // namespace openvpn::UDPTransport
342
343#endif
#define OPENVPN_ASYNC_HANDLER
Definition bigmutex.hpp:36
typename RESOLVER_TYPE::results_type results_type
Definition asio.hpp:97
virtual void async_resolve_name(const std::string &host, const std::string &port)
Definition asio.hpp:125
static Addr from_asio(const openvpn_io::ip::address &addr)
Definition ip.hpp:576
std::string to_string() const
Definition ip.hpp:528
const char * str() const
Definition protocol.hpp:212
The smart pointer class.
Definition rc.hpp:119
void reset() noexcept
Points this RCPtr<T> to nullptr safely.
Definition rc.hpp:290
void process_push(const OptionList &opt)
RCPtr< ClientConfig > Ptr
Definition udpcli.hpp:34
TransportClient::Ptr new_transport_client_obj(openvpn_io::io_context &io_context, TransportClientParent *parent) override
Definition udpcli.hpp:336
void process_push(const OptionList &opt) override
Definition udpcli.hpp:57
bool transport_send_const(const Buffer &buf) override
Definition udpcli.hpp:109
UDPTransport::AsioEndpoint server_endpoint
Definition udpcli.hpp:332
size_t transport_send_queue_size() override
Definition udpcli.hpp:133
bool transport_send_queue_empty() override
Definition udpcli.hpp:119
openvpn_io::detail::socket_type native_handle() override
Definition udpcli.hpp:163
bool send(const Buffer &buf)
Definition udpcli.hpp:200
void reset_align_adjust(const size_t align_adjust) override
Definition udpcli.hpp:138
TransportClientParent * parent
Definition udpcli.hpp:329
void resolve_callback(const openvpn_io::error_code &error, results_type results) override
Definition udpcli.hpp:247
openvpn_io::ip::udp::resolver resolver
Definition udpcli.hpp:331
void transport_start() override
Definition udpcli.hpp:82
UDPLink< Client * > LinkImpl
Definition udpcli.hpp:79
void transport_reparent(TransportClientParent *parent_arg) override
Definition udpcli.hpp:195
void transport_stop_requeueing() override
Definition udpcli.hpp:129
openvpn_io::ip::udp::socket socket
Definition udpcli.hpp:327
void start_impl_(const openvpn_io::error_code &error)
Definition udpcli.hpp:295
bool transport_has_send_queue() override
Definition udpcli.hpp:124
Protocol transport_protocol() const override
Definition udpcli.hpp:168
ClientConfig::Ptr config
Definition udpcli.hpp:328
bool transport_send(BufferAllocated &buf) override
Definition udpcli.hpp:114
Client(openvpn_io::io_context &io_context_arg, ClientConfig *config_arg, TransportClientParent *parent_arg)
Definition udpcli.hpp:183
IP::Addr server_endpoint_addr() const override
Definition udpcli.hpp:153
void server_endpoint_info(std::string &host, std::string &port, std::string &proto, std::string &ip_addr) const override
Definition udpcli.hpp:144
void udp_read_handler(PacketFrom::SPtr &pfp)
Definition udpcli.hpp:225
unsigned short server_endpoint_port() const override
Definition udpcli.hpp:158
#define unlikely(x)
Definition likely.hpp:22
#define OPENVPN_LOG(args)
@ UDP_CONNECT_ERROR
Definition error.hpp:51
@ SOCKET_PROTECT_ERROR
Definition error.hpp:36
openvpn_io::ip::udp::endpoint AsioEndpoint
Definition udplink.hpp:44
virtual void transport_connecting()=0
virtual void transport_pre_resolve()=0
virtual void transport_error(const Error::Type fatal_err, const std::string &err_text)=0
virtual void transport_wait()=0
virtual void transport_recv(BufferAllocated &buf)=0
RCPtr< TransportClient > Ptr
Definition transbase.hpp:37
std::unique_ptr< PacketFrom > SPtr
Definition udplink.hpp:54
proxy_host_port port
proxy_host_port host