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 Linux.
13
14#ifndef OPENVPN_TUN_LINUX_CLIENT_TUNCLI_H
15#define OPENVPN_TUN_LINUX_CLIENT_TUNCLI_H
16
21#include <openvpn/tun/tunio.hpp>
24
26
28{
29 typedef std::unique_ptr<PacketFrom> SPtr;
31};
32
33template <typename ReadHandler>
34class Tun : public TunIO<ReadHandler, PacketFrom, openvpn_io::posix::stream_descriptor>
35{
37
38 public:
39 typedef RCPtr<Tun> Ptr;
40
41 Tun(openvpn_io::io_context &io_context,
42 ReadHandler read_handler_arg,
43 const Frame::Ptr &frame_arg,
44 const SessionStats::Ptr &stats_arg,
45 const int socket,
46 const std::string &name)
47 : Base(read_handler_arg, frame_arg, stats_arg)
48 {
51 Base::stream = new openvpn_io::posix::stream_descriptor(io_context, socket);
52 OPENVPN_LOG_TUN(Base::name_ << " opened");
53 }
54
56 {
57 Base::stop();
58 }
59};
60
62
64{
65 public:
67
68 std::string dev_name;
69 int txqueuelen = 200;
70
72
74
75 int n_parallel = 8;
78
81
82 void load(const OptionList &opt)
83 {
84 // set a default MTU
85 if (!tun_prop.mtu)
87
88 // parse "dev" option
89 if (dev_name.empty())
90 {
91 const Option *dev = opt.get_ptr("dev");
92 if (dev)
93 dev_name = dev->get(1, 64);
94 }
95 }
96
97 static Ptr new_obj()
98 {
99 return new ClientConfig;
100 }
101
102 TunClient::Ptr new_tun_client_obj(openvpn_io::io_context &io_context,
103 TunClientParent &parent,
104 TransportClient *transcli) override;
105
107 {
109 return tun_setup_factory->new_setup_obj();
110 else
112 }
113
114 bool supports_epoch_data() override
115 {
116 /* The normal tun implementation that uses the internal data channel */
117 return true;
118 }
119
120 private:
122 {
123 }
124};
125
126class Client : public TunClient
127{
128 friend class ClientConfig; // calls constructor
129 friend class TunIO<Client *, PacketFrom, openvpn_io::posix::stream_descriptor>; // calls tun_read_handler
130
132
133 public:
134 void tun_start(const OptionList &opt, TransportClient &transcli, CryptoDCSettings &) override
135 {
136 if (!impl)
137 {
138 halt = false;
139
140 if (config->tun_persist)
141 {
142 OPENVPN_LOG("TunPersist: long-term session scope");
143 tun_persist = config->tun_persist; // long-term persistent
144 }
145 else
146 {
147 OPENVPN_LOG("TunPersist: short-term connection scope");
148 tun_persist.reset(new TunPersist(true, TunWrapObjRetain::NO_RETAIN, nullptr)); // short-term
149 }
150
151 try
152 {
153 const IP::Addr server_addr = transcli.server_endpoint_addr();
154
155 int sd = -1;
156
157 // Check if persisted tun session matches properties of to-be-created session
158 if (tun_persist->use_persisted_tun(server_addr, config->tun_prop, opt))
159 {
160 state = tun_persist->state();
161 sd = tun_persist->obj();
162 state = tun_persist->state();
163 OPENVPN_LOG("TunPersist: reused tun context");
164 }
165 else
166 {
167 // notify parent
169
170 // close old tun handle if persisted
171 tun_persist->close();
172
173 // parse pushed options
176 state.get(),
177 config->stats.get(),
178 server_addr,
179 config->tun_prop,
180 opt,
181 nullptr,
182 false);
183
184 OPENVPN_LOG("CAPTURED OPTIONS:" << std::endl
185 << po->to_string());
186
187 // create new tun setup object
188 tun_setup = config->new_setup_obj();
189
190 // create config object for tun setup layer
192 tsconf.layer = config->tun_prop.layer;
193 tsconf.dev_name = config->dev_name;
194 tsconf.txqueuelen = config->txqueuelen;
195 tsconf.add_bypass_routes_on_establish = true;
196
197 // open/config tun
198 {
199 std::ostringstream os;
200 auto os_print = Cleanup([&os]()
201 { OPENVPN_LOG_STRING(os.str()); });
202 sd = tun_setup->establish(*po, &tsconf, nullptr, os);
203 }
204
205#if defined(HAVE_JSON)
206 if (config->generate_tun_builder_capture_event)
207 {
208 // create an event with TunBuilderCapture data as JSON
209 parent.tun_event(new ClientEvent::InfoJSON("TUN_BUILDER_CAPTURE", po->to_json()));
210 }
211#endif
212
213 // persist tun settings state
214 state->iface_name = tsconf.iface_name;
215 tun_persist->persist_tun_state(sd, state);
216
217 // enable tun_setup destructor
218 tun_persist->add_destructor(tun_setup);
219 }
220
221 // start tun
223 this,
224 config->frame,
225 config->stats,
226 sd,
227 state->iface_name));
228 impl->start(config->n_parallel);
229
230 // signal that we are connected
232 }
233 catch (const std::exception &e)
234 {
235 if (tun_persist)
236 tun_persist->close();
237
238 stop();
240 }
241 }
242 }
243
244 bool tun_send(BufferAllocated &buf) override
245 {
246 return send(buf);
247 }
248
249 std::string tun_name() const override
250 {
251 if (impl)
252 return impl->name();
253 else
254 return "UNDEF_TUN";
255 }
256
257 std::string vpn_ip4() const override
258 {
259 if (state->vpn_ip4_addr.specified())
260 return state->vpn_ip4_addr.to_string();
261 else
262 return "";
263 }
264
265 std::string vpn_ip6() const override
266 {
267 if (state->vpn_ip6_addr.specified())
268 return state->vpn_ip6_addr.to_string();
269 else
270 return "";
271 }
272
273 std::string vpn_gw4() const override
274 {
275 if (state->vpn_ip4_gw.specified())
276 return state->vpn_ip4_gw.to_string();
277 else
278 return "";
279 }
280
281 std::string vpn_gw6() const override
282 {
283 if (state->vpn_ip6_gw.specified())
284 return state->vpn_ip6_gw.to_string();
285 else
286 return "";
287 }
288
289 int vpn_mtu() const override
290 {
291 return state->mtu;
292 }
293
294 void set_disconnect() override
295 {
296 }
297
298 void stop() override
299 {
300 stop_();
301 }
302 virtual ~Client()
303 {
304 stop_();
305 }
306
307 void apply_push_update(const OptionList &opt, TransportClient &transcli) override
308 {
309 stop_();
310 if (impl)
311 {
312 impl.reset();
313 }
314
315 // this has to be done in post, because we need to wait
316 // for all async tun read requests to complete
317 openvpn_io::post(io_context, [self = Ptr(this), opt, &transcli]
318 {
321 self->tun_start(opt, transcli, c); });
322 }
323
324 private:
325 Client(openvpn_io::io_context &io_context_arg,
326 ClientConfig *config_arg,
327 TunClientParent &parent_arg)
328 : io_context(io_context_arg),
329 config(config_arg),
330 parent(parent_arg),
331 state(new TunProp::State()),
332 halt(false)
333 {
334 }
335
336 bool send(Buffer &buf)
337 {
338 if (impl)
339 return impl->write(buf);
340 else
341 return false;
342 }
343
344 void tun_read_handler(PacketFrom::SPtr &pfp) // called by TunImpl
345 {
346 parent.tun_recv(pfp->buf);
347 }
348
349 void tun_error_handler(const Error::Type errtype, // called by TunImpl
350 const openvpn_io::error_code *error)
351 {
352 }
353
354 void stop_()
355 {
356 if (!halt)
357 {
358 halt = true;
359
360 // stop tun
361 if (impl)
362 impl->stop();
363
365 }
366 }
367
368 openvpn_io::io_context &io_context;
375 bool halt;
376};
377
378inline TunClient::Ptr ClientConfig::new_tun_client_obj(openvpn_io::io_context &io_context,
379 TunClientParent &parent,
380 TransportClient *transcli)
381{
382 return TunClient::Ptr(new Client(io_context, this, parent));
383}
384
385} // namespace openvpn::TunLinux
386
387#endif // OPENVPN_TUN_LINUX_CLIENT_TUNCLI_H
#define OPENVPN_ASYNC_HANDLER
Definition bigmutex.hpp:36
const Option * get_ptr(const std::string &name) const
Definition options.hpp:1186
const std::string & get(const size_t index, const size_t max_len) const
Definition options.hpp:187
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
Json::Value to_json() const
Serializes the tunnel configuration to a JSON object.
Definition capture.hpp:1011
std::string to_string() const
Converts the tunnel configuration to a human-readable string representation.
Definition capture.hpp:968
void load(const OptionList &opt)
Definition tuncli.hpp:82
TunBuilderSetup::Base::Ptr new_setup_obj()
Definition tuncli.hpp:106
bool supports_epoch_data() override
Definition tuncli.hpp:114
RCPtr< ClientConfig > Ptr
Definition tuncli.hpp:66
SessionStats::Ptr stats
Definition tuncli.hpp:77
TunPersist::Ptr tun_persist
Definition tuncli.hpp:80
TunClient::Ptr new_tun_client_obj(openvpn_io::io_context &io_context, TunClientParent &parent, TransportClient *transcli) override
Definition tuncli.hpp:378
TunBuilderSetup::Factory::Ptr tun_setup_factory
Definition tuncli.hpp:79
TunClientParent & parent
Definition tuncli.hpp:371
Client(openvpn_io::io_context &io_context_arg, ClientConfig *config_arg, TunClientParent &parent_arg)
Definition tuncli.hpp:325
std::string tun_name() const override
Definition tuncli.hpp:249
void tun_error_handler(const Error::Type errtype, const openvpn_io::error_code *error)
Definition tuncli.hpp:349
TunProp::State::Ptr state
Definition tuncli.hpp:373
TunBuilderSetup::Base::Ptr tun_setup
Definition tuncli.hpp:374
void apply_push_update(const OptionList &opt, TransportClient &transcli) override
Notifies tun client about received PUSH_UPDATE control channel message.
Definition tuncli.hpp:307
bool tun_send(BufferAllocated &buf) override
Definition tuncli.hpp:244
void set_disconnect() override
Definition tuncli.hpp:294
ClientConfig::Ptr config
Definition tuncli.hpp:370
std::string vpn_ip6() const override
Definition tuncli.hpp:265
Tun< Client * > TunImpl
Definition tuncli.hpp:131
void tun_read_handler(PacketFrom::SPtr &pfp)
Definition tuncli.hpp:344
TunPersist::Ptr tun_persist
Definition tuncli.hpp:369
void tun_start(const OptionList &opt, TransportClient &transcli, CryptoDCSettings &) override
Definition tuncli.hpp:134
openvpn_io::io_context & io_context
Definition tuncli.hpp:368
std::string vpn_gw4() const override
Definition tuncli.hpp:273
void stop() override
Definition tuncli.hpp:298
int vpn_mtu() const override
Definition tuncli.hpp:289
std::string vpn_gw6() const override
Definition tuncli.hpp:281
bool send(Buffer &buf)
Definition tuncli.hpp:336
std::string vpn_ip4() const override
Definition tuncli.hpp:257
TunIO< ReadHandler, PacketFrom, openvpn_io::posix::stream_descriptor > Base
Definition tuncli.hpp:36
Tun(openvpn_io::io_context &io_context, ReadHandler read_handler_arg, const Frame::Ptr &frame_arg, const SessionStats::Ptr &stats_arg, const int socket, const std::string &name)
Definition tuncli.hpp:41
RCPtr< Tun > Ptr
Definition tuncli.hpp:39
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_LOG(args)
#define OPENVPN_LOG_STRING(str)
TunPersistTemplate< ScopedFD > TunPersist
Definition tuncli.hpp:61
@ 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_event(ClientEvent::Base::Ptr ev)
Definition tunbase.hpp:94
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
std::unique_ptr< PacketFrom > SPtr
Definition tuncli.hpp:29
std::ostringstream os
#define OPENVPN_LOG_TUN(x)
Definition tunlog.hpp:26