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 using SPtr = std::unique_ptr<PacketFrom>;
31};
32
33template <typename ReadHandler>
34class Tun : public TunIO<ReadHandler, PacketFrom, openvpn_io::posix::stream_descriptor>
35{
37
38 public:
39 using Ptr = RCPtr<Tun>;
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();
111 }
112
113 bool supports_epoch_data() override
114 {
115 /* The normal tun implementation that uses the internal data channel */
116 return true;
117 }
118
119 private:
120 ClientConfig() = default;
121};
122
123class Client : public TunClient
124{
125 friend class ClientConfig; // calls constructor
126 friend class TunIO<Client *, PacketFrom, openvpn_io::posix::stream_descriptor>; // calls tun_read_handler
127
129
130 public:
131 void tun_start(const OptionList &opt, TransportClient &transcli, CryptoDCSettings &) override
132 {
133 if (!impl)
134 {
135 halt = false;
136
137 if (config->tun_persist)
138 {
139 OPENVPN_LOG("TunPersist: long-term session scope");
140 tun_persist = config->tun_persist; // long-term persistent
141 }
142 else
143 {
144 OPENVPN_LOG("TunPersist: short-term connection scope");
145 tun_persist.reset(new TunPersist(true, TunWrapObjRetain::NO_RETAIN, nullptr)); // short-term
146 }
147
148 try
149 {
150 const IP::Addr server_addr = transcli.server_endpoint_addr();
151
152 int sd = -1;
153
154 // Check if persisted tun session matches properties of to-be-created session
155 if (tun_persist->use_persisted_tun(server_addr, config->tun_prop, opt))
156 {
157 state = tun_persist->state();
158 sd = tun_persist->obj();
159 state = tun_persist->state();
160 OPENVPN_LOG("TunPersist: reused tun context");
161 }
162 else
163 {
164 // notify parent
166
167 // close old tun handle if persisted
168 tun_persist->close();
169
170 // parse pushed options
173 state.get(),
174 config->stats.get(),
175 server_addr,
176 config->tun_prop,
177 opt,
178 nullptr,
179 false);
180
181 OPENVPN_LOG("CAPTURED OPTIONS:\n"
182 << po->to_string());
183
184 // create new tun setup object
185 tun_setup = config->new_setup_obj();
186
187 // create config object for tun setup layer
189 tsconf.layer = config->tun_prop.layer;
190 tsconf.dev_name = config->dev_name;
191 tsconf.txqueuelen = config->txqueuelen;
192 tsconf.add_bypass_routes_on_establish = true;
193
194 // open/config tun
195 {
196 std::ostringstream os;
197 auto os_print = Cleanup([&os]()
198 { OPENVPN_LOG_STRING(os.str()); });
199 sd = tun_setup->establish(*po, &tsconf, nullptr, os);
200 }
201
202#ifdef HAVE_JSON
203 if (config->generate_tun_builder_capture_event)
204 {
205 // create an event with TunBuilderCapture data as JSON
206 parent.tun_event(new ClientEvent::InfoJSON("TUN_BUILDER_CAPTURE", po->to_json()));
207 }
208#endif
209
210 // persist tun settings state
211 state->iface_name = tsconf.iface_name;
212 tun_persist->persist_tun_state(sd, state);
213
214 // enable tun_setup destructor
215 tun_persist->add_destructor(tun_setup);
216 }
217
218 // start tun
220 this,
221 config->frame,
222 config->stats,
223 sd,
224 state->iface_name));
225 impl->start(config->n_parallel);
226
227 // signal that we are connected
229 }
230 catch (const std::exception &e)
231 {
232 if (tun_persist)
233 tun_persist->close();
234
235 stop();
237 }
238 }
239 }
240
241 bool tun_send(BufferAllocated &buf) override
242 {
243 return send(buf);
244 }
245
246 std::string tun_name() const override
247 {
248 if (impl)
249 return impl->name();
250 return "UNDEF_TUN";
251 }
252
253 std::string vpn_ip4() const override
254 {
255 if (state->vpn_ip4_addr.specified())
256 return state->vpn_ip4_addr.to_string();
257 return "";
258 }
259
260 std::string vpn_ip6() const override
261 {
262 if (state->vpn_ip6_addr.specified())
263 return state->vpn_ip6_addr.to_string();
264 return "";
265 }
266
267 std::string vpn_gw4() const override
268 {
269 if (state->vpn_ip4_gw.specified())
270 return state->vpn_ip4_gw.to_string();
271 return "";
272 }
273
274 std::string vpn_gw6() const override
275 {
276 if (state->vpn_ip6_gw.specified())
277 return state->vpn_ip6_gw.to_string();
278 return "";
279 }
280
281 int vpn_mtu() const override
282 {
283 return state->mtu;
284 }
285
286 void set_disconnect() override
287 {
288 }
289
290 void stop() override
291 {
292 stop_();
293 }
294 virtual ~Client()
295 {
296 stop_();
297 }
298
299 void apply_push_update(const OptionList &opt, TransportClient &transcli) override
300 {
301 stop_();
302 if (impl)
303 {
304 impl.reset();
305 }
306
307 // this has to be done in post, because we need to wait
308 // for all async tun read requests to complete
309 openvpn_io::post(io_context, [self = Ptr(this), opt, &transcli]
310 {
313 self->tun_start(opt, transcli, c); });
314 }
315
316 private:
317 Client(openvpn_io::io_context &io_context_arg,
318 ClientConfig *config_arg,
319 TunClientParent &parent_arg)
320 : io_context(io_context_arg),
321 config(config_arg),
322 parent(parent_arg),
323 state(new TunProp::State()),
324 halt(false)
325 {
326 }
327
328 bool send(Buffer &buf)
329 {
330 if (impl)
331 return impl->write(buf);
332 return false;
333 }
334
335 void tun_read_handler(PacketFrom::SPtr &pfp) // called by TunImpl
336 {
337 parent.tun_recv(pfp->buf);
338 }
339
340 void tun_error_handler(const Error::Type errtype, // called by TunImpl
341 const openvpn_io::error_code *error)
342 {
343 }
344
345 void stop_()
346 {
347 if (!halt)
348 {
349 halt = true;
350
351 // stop tun
352 if (impl)
353 impl->stop();
354
356 }
357 }
358
359 openvpn_io::io_context &io_context;
366 bool halt;
367};
368
369inline TunClient::Ptr ClientConfig::new_tun_client_obj(openvpn_io::io_context &io_context,
370 TunClientParent &parent,
371 TransportClient *transcli)
372{
373 return TunClient::Ptr(new Client(io_context, this, parent));
374}
375
376} // namespace openvpn::TunLinux
377
378#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:1174
const std::string & get(const size_t index, const size_t max_len) const
Definition options.hpp:184
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:113
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:369
TunBuilderSetup::Factory::Ptr tun_setup_factory
Definition tuncli.hpp:79
Tun< Client * > TunImpl
Definition tuncli.hpp:128
TunClientParent & parent
Definition tuncli.hpp:362
Client(openvpn_io::io_context &io_context_arg, ClientConfig *config_arg, TunClientParent &parent_arg)
Definition tuncli.hpp:317
std::string tun_name() const override
Definition tuncli.hpp:246
void tun_error_handler(const Error::Type errtype, const openvpn_io::error_code *error)
Definition tuncli.hpp:340
TunProp::State::Ptr state
Definition tuncli.hpp:364
TunBuilderSetup::Base::Ptr tun_setup
Definition tuncli.hpp:365
void apply_push_update(const OptionList &opt, TransportClient &transcli) override
Notifies tun client about received PUSH_UPDATE control channel message.
Definition tuncli.hpp:299
bool tun_send(BufferAllocated &buf) override
Definition tuncli.hpp:241
void set_disconnect() override
Definition tuncli.hpp:286
ClientConfig::Ptr config
Definition tuncli.hpp:361
std::string vpn_ip6() const override
Definition tuncli.hpp:260
void tun_read_handler(PacketFrom::SPtr &pfp)
Definition tuncli.hpp:335
TunPersist::Ptr tun_persist
Definition tuncli.hpp:360
void tun_start(const OptionList &opt, TransportClient &transcli, CryptoDCSettings &) override
Definition tuncli.hpp:131
openvpn_io::io_context & io_context
Definition tuncli.hpp:359
std::string vpn_gw4() const override
Definition tuncli.hpp:267
void stop() override
Definition tuncli.hpp:290
int vpn_mtu() const override
Definition tuncli.hpp:281
std::string vpn_gw6() const override
Definition tuncli.hpp:274
bool send(Buffer &buf)
Definition tuncli.hpp:328
std::string vpn_ip4() const override
Definition tuncli.hpp:253
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
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
CleanupType< F > Cleanup(F method) noexcept
Definition cleanup.hpp:43
@ TUN_MTU_DEFAULT
Definition tunmtu.hpp:20
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