OpenVPN 3 Core Library
Loading...
Searching...
No Matches
tuncli.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// Client tun interface for Mac OS X
13
14#ifndef OPENVPN_TUN_MAC_CLIENT_TUNCLI_H
15#define OPENVPN_TUN_MAC_CLIENT_TUNCLI_H
16
17#include <string>
18#include <sstream>
19#include <memory>
20
28#include <openvpn/tun/tunio.hpp>
31
32#ifdef TEST_EER // test emulated exclude routes
34#endif
35
36namespace openvpn::TunMac {
37
38OPENVPN_EXCEPTION(tun_mac_error);
39
40// struct used to pass received tun packets
42{
43 typedef std::unique_ptr<PacketFrom> SPtr;
45};
46
47// tun interface wrapper for Mac OS X
48template <typename ReadHandler, typename TunPersist>
49class Tun : public TunIO<ReadHandler, PacketFrom, TunWrapAsioStream<TunPersist>>
50{
52
53 public:
54 typedef RCPtr<Tun> Ptr;
55
56 Tun(const typename TunPersist::Ptr &tun_persist,
57 const std::string &name,
58 const bool retain_stream,
59 const bool tun_prefix,
60 ReadHandler read_handler,
61 const Frame::Ptr &frame,
63 : Base(read_handler, frame, stats)
64 {
69 }
70};
71
72// These types manage the underlying tun driver fd
73typedef openvpn_io::posix::stream_descriptor TUNStream;
76
77class Client;
78
80{
81 public:
83
85 int n_parallel = 8; // number of parallel async reads on tun socket
86
89
91
92 Stop *stop = nullptr;
93
95
97 {
99 return tun_setup_factory->new_setup_obj();
100 else
101 return new TunMac::Setup();
102 }
103
104 static Ptr new_obj()
105 {
106 return new ClientConfig;
107 }
108
109 bool supports_epoch_data() override
110 {
111 return true;
112 }
113
114 TunClient::Ptr new_tun_client_obj(openvpn_io::io_context &io_context,
115 TunClientParent &parent,
116 TransportClient *transcli) override;
117
118 // return true if layer 2 tunnels are supported
119 bool layer_2_supported() const override
120 {
121#if defined(MAC_TUNTAP_FALLBACK)
122 return false; // change to true after TAP support is added
123#else
124 return false; // utun device doesn't support TAP
125#endif
126 }
127
128 // called just prior to transmission of Disconnect event
129 void finalize(const bool disconnected) override
130 {
131 if (disconnected)
133 }
134};
135
136class Client : public TunClient
137{
138 friend class ClientConfig; // calls constructor
139 friend class TunIO<Client *, PacketFrom, TunWrapAsioStream<TunPersist>>; // calls tun_read_handler
140
142
143 public:
144 void tun_start(const OptionList &opt, TransportClient &transcli, CryptoDCSettings &) override
145 {
146 if (!impl)
147 {
148 halt = false;
149 if (config->tun_persist)
150 {
151 OPENVPN_LOG("TunPersist: long-term session scope");
152 tun_persist = config->tun_persist;
153 }
154 else
155 {
156 OPENVPN_LOG("TunPersist: short-term connection scope");
158 }
159
160 try
161 {
162 const IP::Addr server_addr = transcli.server_endpoint_addr();
163
164 // Check if persisted tun session matches properties of to-be-created session
165 if (tun_persist->use_persisted_tun(server_addr, config->tun_prop, opt))
166 {
167 state = tun_persist->state();
168 OPENVPN_LOG("TunPersist: reused tun context");
169 }
170 else
171 {
172 OPENVPN_LOG("TunPersist: new tun context");
173
174 // notify parent
176
177 // close old tun handle if persisted
178 tun_persist->close();
179
180 // emulated exclude routes
182#ifdef TEST_EER
183 eer_factory.reset(new EmulateExcludeRouteFactoryImpl(true));
184#endif
185 // parse pushed options
188 state.get(),
189 config->stats.get(),
190 server_addr,
191 config->tun_prop,
192 opt,
193 eer_factory.get(),
194 false);
195
196 // handle MTU default
197 if (!po->mtu)
198 po->mtu = TUN_MTU_DEFAULT;
199
200 OPENVPN_LOG("CAPTURED OPTIONS:" << std::endl
201 << po->to_string());
202
203 // create new tun setup object
204 tun_setup = config->new_setup_obj();
205
206 // create config object for tun setup layer
207 Setup::Config tsconf;
208 tsconf.iface_name = state->iface_name;
209 tsconf.layer = config->tun_prop.layer;
210
211 // open/config tun
212 int fd = -1;
213 {
214 std::ostringstream os;
215 auto os_print = Cleanup([&os]()
216 { OPENVPN_LOG_STRING(os.str()); });
217 fd = tun_setup->establish(*po, &tsconf, config->stop, os);
218 }
219
220 // create ASIO wrapper for tun fd
221 TUNStream *ts = new TUNStream(io_context, fd);
222
223 // persist tun settings state
224 state->iface_name = tsconf.iface_name;
225 state->tun_prefix = tsconf.tun_prefix;
226 if (tun_persist->persist_tun_state(ts, state))
227 OPENVPN_LOG("TunPersist: saving tun context:" << std::endl
228 << tun_persist->options());
229
230 // enable tun_setup destructor
231 tun_persist->add_destructor(tun_setup);
232 }
233
234 // configure tun interface packet forwarding
236 state->iface_name,
237 true,
238 state->tun_prefix,
239 this,
240 config->frame,
241 config->stats));
242 impl->start(config->n_parallel);
243
244 // signal that we are connected
246 }
247 catch (const std::exception &e)
248 {
249 if (tun_persist)
250 tun_persist->close();
251 stop();
253 const ExceptionCode *ec = dynamic_cast<const ExceptionCode *>(&e);
254 if (ec && ec->code_defined())
255 err = ec->code();
256 parent.tun_error(err, e.what());
257 }
258 }
259 }
260
261 bool tun_send(BufferAllocated &buf) override
262 {
263 return send(buf);
264 }
265
266 std::string tun_name() const override
267 {
268 if (impl)
269 return impl->name();
270 else
271 return "UNDEF_TUN";
272 }
273
274 std::string vpn_ip4() const override
275 {
276 if (state->vpn_ip4_addr.specified())
277 return state->vpn_ip4_addr.to_string();
278 else
279 return "";
280 }
281
282 std::string vpn_ip6() const override
283 {
284 if (state->vpn_ip6_addr.specified())
285 return state->vpn_ip6_addr.to_string();
286 else
287 return "";
288 }
289
290 std::string vpn_gw4() const override
291 {
292 if (state->vpn_ip4_gw.specified())
293 return state->vpn_ip4_gw.to_string();
294 else
295 return "";
296 }
297
298 std::string vpn_gw6() const override
299 {
300 if (state->vpn_ip6_gw.specified())
301 return state->vpn_ip6_gw.to_string();
302 else
303 return "";
304 }
305
306 int vpn_mtu() const override
307 {
308 return state->mtu;
309 }
310
311 void set_disconnect() override
312 {
313 }
314
315 void stop() override
316 {
317 stop_();
318 }
319 virtual ~Client()
320 {
321 stop_();
322 }
323
324 void apply_push_update(const OptionList &opt, TransportClient &cli) override
325 {
326 stop_();
327 if (impl)
328 {
329 impl.reset();
330 }
331
332 // this has to be done in post, because we need to wait
333 // for all async tun read requests to complete
334 openvpn_io::post(io_context,
335 [self = Ptr(this), opt, &cli]
336 {
339 self->tun_start(opt, cli, c);
340 });
341 }
342
343 private:
344 Client(openvpn_io::io_context &io_context_arg,
345 ClientConfig *config_arg,
346 TunClientParent &parent_arg)
347 : io_context(io_context_arg),
348 config(config_arg),
349 parent(parent_arg),
350 halt(false),
351 state(new TunProp::State())
352 {
353 }
354
355 bool send(Buffer &buf)
356 {
357 if (impl)
358 return impl->write(buf);
359 else
360 return false;
361 }
362
363 void tun_read_handler(PacketFrom::SPtr &pfp) // called by TunImpl
364 {
365 parent.tun_recv(pfp->buf);
366 }
367
368 void tun_error_handler(const Error::Type errtype, // called by TunImpl
369 const openvpn_io::error_code *error)
370 {
371 parent.tun_error(Error::TUN_ERROR, "TUN I/O error");
372 }
373
374 void stop_()
375 {
376 if (!halt)
377 {
378 halt = true;
379
380 // stop tun
381 if (impl)
382 impl->stop();
384 }
385 }
386
387 openvpn_io::io_context &io_context;
388 TunPersist::Ptr tun_persist; // contains the tun device fd
392 bool halt;
395};
396
397inline TunClient::Ptr ClientConfig::new_tun_client_obj(openvpn_io::io_context &io_context,
398 TunClientParent &parent,
399 TransportClient *transcli)
400{
401 return TunClient::Ptr(new Client(io_context, this, parent));
402}
403
404} // namespace openvpn::TunMac
405
406#endif
#define OPENVPN_ASYNC_HANDLER
Definition bigmutex.hpp:36
Error::Type code() const
Definition excode.hpp:47
bool code_defined() const
Definition excode.hpp:56
The smart pointer class.
Definition rc.hpp:119
void reset() noexcept
Points this RCPtr<T> to nullptr safely.
Definition rc.hpp:290
T * get() const noexcept
Returns the raw pointer to the object T, or nullptr.
Definition rc.hpp:321
std::string to_string() const
Converts the tunnel configuration to a human-readable string representation.
Definition capture.hpp:968
TunClient::Ptr new_tun_client_obj(openvpn_io::io_context &io_context, TunClientParent &parent, TransportClient *transcli) override
Definition tuncli.hpp:397
TunProp::Config tun_prop
Definition tuncli.hpp:84
bool layer_2_supported() const override
Definition tuncli.hpp:119
TunBuilderSetup::Base::Ptr new_setup_obj()
Definition tuncli.hpp:96
bool supports_epoch_data() override
Definition tuncli.hpp:109
TunBuilderSetup::Factory::Ptr tun_setup_factory
Definition tuncli.hpp:94
TunPersist::Ptr tun_persist
Definition tuncli.hpp:90
SessionStats::Ptr stats
Definition tuncli.hpp:88
void finalize(const bool disconnected) override
Definition tuncli.hpp:129
RCPtr< ClientConfig > Ptr
Definition tuncli.hpp:82
bool tun_send(BufferAllocated &buf) override
Definition tuncli.hpp:261
bool send(Buffer &buf)
Definition tuncli.hpp:355
std::string vpn_ip4() const override
Definition tuncli.hpp:274
TunProp::State::Ptr state
Definition tuncli.hpp:393
void tun_start(const OptionList &opt, TransportClient &transcli, CryptoDCSettings &) override
Definition tuncli.hpp:144
std::string vpn_ip6() const override
Definition tuncli.hpp:282
void tun_read_handler(PacketFrom::SPtr &pfp)
Definition tuncli.hpp:363
TunBuilderSetup::Base::Ptr tun_setup
Definition tuncli.hpp:394
void apply_push_update(const OptionList &opt, TransportClient &cli) override
Notifies tun client about received PUSH_UPDATE control channel message.
Definition tuncli.hpp:324
void stop() override
Definition tuncli.hpp:315
Tun< Client *, TunPersist > TunImpl
Definition tuncli.hpp:141
ClientConfig::Ptr config
Definition tuncli.hpp:389
TunClientParent & parent
Definition tuncli.hpp:390
Client(openvpn_io::io_context &io_context_arg, ClientConfig *config_arg, TunClientParent &parent_arg)
Definition tuncli.hpp:344
std::string vpn_gw6() const override
Definition tuncli.hpp:298
openvpn_io::io_context & io_context
Definition tuncli.hpp:387
std::string tun_name() const override
Definition tuncli.hpp:266
int vpn_mtu() const override
Definition tuncli.hpp:306
std::string vpn_gw4() const override
Definition tuncli.hpp:290
void tun_error_handler(const Error::Type errtype, const openvpn_io::error_code *error)
Definition tuncli.hpp:368
void set_disconnect() override
Definition tuncli.hpp:311
TunPersist::Ptr tun_persist
Definition tuncli.hpp:388
RCPtr< Tun > Ptr
Definition tuncli.hpp:54
TunIO< ReadHandler, PacketFrom, TunWrapAsioStream< TunPersist > > Base
Definition tuncli.hpp:51
Tun(const typename TunPersist::Ptr &tun_persist, const std::string &name, const bool retain_stream, const bool tun_prefix, ReadHandler read_handler, const Frame::Ptr &frame, const SessionStats::Ptr &stats)
Definition tuncli.hpp:56
static void configure_builder(TunBuilderBase *tb, State *state, SessionStats *stats, const IP::Addr &server_addr, const Config &config, const OptionList &opt, const EmulateExcludeRouteFactory *eer_factory, const bool quiet)
Definition tunprop.hpp:92
#define OPENVPN_EXCEPTION(C)
#define OPENVPN_LOG(args)
#define OPENVPN_LOG_STRING(str)
ScopedAsioStream< TUNStream > ScopedTUNStream
Definition tuncli.hpp:74
openvpn_io::posix::stream_descriptor TUNStream
Definition tuncli.hpp:73
TunPersistTemplate< ScopedTUNStream > TunPersist
Definition tuncli.hpp:75
@ TUN_MTU_DEFAULT
Definition tunmtu.hpp:20
CleanupType< F > Cleanup(F method) noexcept
Definition cleanup.hpp:43
virtual IP::Addr server_endpoint_addr() const =0
virtual void tun_error(const Error::Type fatal_err, const std::string &err_text)=0
virtual void tun_connected()=0
virtual void tun_pre_tun_config()=0
virtual void tun_recv(BufferAllocated &buf)=0
RCPtr< TunClient > Ptr
Definition tunbase.hpp:34
BufferAllocated buf
Definition tuncli.hpp:44
std::unique_ptr< PacketFrom > SPtr
Definition tuncli.hpp:43
std::ostringstream os