OpenVPN 3 Core Library
Loading...
Searching...
No Matches
utun.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
13// Thanks to Jonathan Levin for proof-of-concept utun code for Mac OS X.
14// http://newosxbook.com/src.jl?tree=listings&file=17-15-utun.c
15
16// Open a utun device on Mac OS X.
17
18#ifndef OPENVPN_TUN_MAC_UTUN_H
19#define OPENVPN_TUN_MAC_UTUN_H
20
21#include <sys/types.h>
22#include <sys/ioctl.h>
23#include <sys/socket.h>
24#include <sys/sys_domain.h>
25#include <sys/kern_control.h>
26#include <net/if_utun.h>
27#include <errno.h>
28#include <stdio.h>
29#include <string.h>
30#include <syslog.h>
31#include <unistd.h>
32#include <stdlib.h>
33
34#include <string>
35
40
43
44// Open specific utun device unit and return fd.
45// If the unit number is already in use, return -1.
46// Throw exceptions for all other errors.
47// Return the iface name in name.
48inline int utun_open(std::string &name, const int unit)
49{
50 struct sockaddr_ctl sc;
51 struct ctl_info ctlInfo;
52
53 memset(&ctlInfo, 0, sizeof(ctlInfo));
54 if (strlcpy(ctlInfo.ctl_name, UTUN_CONTROL_NAME, sizeof(ctlInfo.ctl_name))
55 >= sizeof(ctlInfo.ctl_name))
56 throw utun_error("UTUN_CONTROL_NAME too long");
57
58 ScopedFD fd(socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL));
59 if (!fd.defined())
60 throw utun_error("socket(SYSPROTO_CONTROL)");
61
62 if (ioctl(fd(), CTLIOCGINFO, &ctlInfo) == -1)
63 throw utun_error("ioctl(CTLIOCGINFO)");
64
65 sc.sc_id = ctlInfo.ctl_id;
66 sc.sc_len = sizeof(sc);
67 sc.sc_family = AF_SYSTEM;
68 sc.ss_sysaddr = AF_SYS_CONTROL;
69 sc.sc_unit = unit + 1;
70 std::memset(sc.sc_reserved, 0, sizeof(sc.sc_reserved));
71
72 // If the connect is successful, a utunX device will be created, where X
73 // is our unit number - 1.
74 if (connect(fd(), (struct sockaddr *)&sc, sizeof(sc)) == -1)
75 return -1;
76
77 // Get iface name of newly created utun dev.
78 char utunname[20];
79 socklen_t utunname_len = sizeof(utunname);
80 if (getsockopt(fd(), SYSPROTO_CONTROL, UTUN_OPT_IFNAME, utunname, &utunname_len))
81 throw utun_error("getsockopt(SYSPROTO_CONTROL)");
82 name = utunname;
83
84 return fd.release();
85}
86
87// Try to open an available utun device unit.
88// Return the iface name in name.
89inline int utun_open(std::string &name)
90{
91 for (int unit = 0; unit < 256; ++unit)
92 {
93 const int fd = utun_open(name, unit);
94 if (fd >= 0)
95 return fd;
96 }
97 throw utun_error("cannot open available utun device");
98}
99} // namespace openvpn::TunMac::UTun
100
101#endif
bool defined() const
Definition scoped_fd.hpp:58
#define OPENVPN_EXCEPTION(C)
int utun_open(std::string &name, const int unit)
Definition utun.hpp:48