mirror of
https://github.com/OpenVPN/openvpn3.git
synced 2024-09-19 19:52:15 +02:00
Added IP address classes for IPv4/v6.
Implemented get_default_gateway() for Mac OS X.
This commit is contained in:
parent
e5c2791c65
commit
bd4673c60f
@ -1,27 +1,190 @@
|
||||
#ifndef OPENVPN_ADDR_IP_H
|
||||
#define OPENVPN_ADDR_IP_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/ostream.hpp>
|
||||
#include <openvpn/addr/ipv4.hpp>
|
||||
#include <openvpn/addr/ipv6.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
namespace IP {
|
||||
|
||||
OPENVPN_EXCEPTION(ip_address_error);
|
||||
OPENVPN_SIMPLE_EXCEPTION(ip_addr_unspecified);
|
||||
OPENVPN_SIMPLE_EXCEPTION(ip_addr_version_inconsistency);
|
||||
OPENVPN_SIMPLE_EXCEPTION(ip_render_exception);
|
||||
OPENVPN_EXCEPTION(ip_parse_exception);
|
||||
|
||||
std::string validate_ip_address(const char *title, const std::string ip_addr)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
const boost::asio::ip::address addr = boost::asio::ip::address::from_string(ip_addr, ec);
|
||||
if (!ec)
|
||||
class Addr
|
||||
{
|
||||
public:
|
||||
enum Version { UNSPEC, V4, V6 };
|
||||
|
||||
Addr()
|
||||
{
|
||||
std::string ret = addr.to_string(ec);
|
||||
if (!ec)
|
||||
return ret;
|
||||
ver = UNSPEC;
|
||||
}
|
||||
OPENVPN_THROW(ip_address_error, "error validating " << title << " IP address '" << ip_addr << "' : " << ec.message());
|
||||
}
|
||||
|
||||
static std::string validate(const std::string& ipstr, const char *title = NULL)
|
||||
{
|
||||
Addr a = from_string(ipstr, title);
|
||||
return a.to_string();
|
||||
}
|
||||
|
||||
static Addr from_string(const std::string& ipstr, const char *title = NULL)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
boost::asio::ip::address a = boost::asio::ip::address::from_string(ipstr, ec);
|
||||
if (ec)
|
||||
{
|
||||
if (!title)
|
||||
title = "";
|
||||
OPENVPN_THROW(ip_parse_exception, "error parsing " << title << " IP address '" << ipstr << "' : " << ec.message());
|
||||
}
|
||||
return from_asio(a);
|
||||
}
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
if (ver != UNSPEC)
|
||||
{
|
||||
const boost::asio::ip::address a = to_asio();
|
||||
boost::system::error_code ec;
|
||||
std::string ret = a.to_string(ec);
|
||||
if (ec)
|
||||
throw ip_render_exception();
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
return "UNSPEC";
|
||||
}
|
||||
|
||||
static Addr from_asio(const boost::asio::ip::address& addr)
|
||||
{
|
||||
if (addr.is_v4())
|
||||
{
|
||||
Addr a;
|
||||
a.ver = V4;
|
||||
a.u.v4 = IPv4::Addr::from_asio(addr.to_v4());
|
||||
return a;
|
||||
}
|
||||
else if (addr.is_v6())
|
||||
{
|
||||
Addr a;
|
||||
a.ver = V6;
|
||||
a.u.v6 = IPv6::Addr::from_asio(addr.to_v6());
|
||||
return a;
|
||||
}
|
||||
else
|
||||
throw ip_addr_unspecified();
|
||||
}
|
||||
|
||||
boost::asio::ip::address to_asio() const
|
||||
{
|
||||
switch (ver)
|
||||
{
|
||||
case V4:
|
||||
return boost::asio::ip::address_v4(u.v4.to_asio());
|
||||
case V6:
|
||||
return boost::asio::ip::address_v6(u.v6.to_asio());
|
||||
default:
|
||||
throw ip_addr_unspecified();
|
||||
}
|
||||
}
|
||||
|
||||
Addr operator&(const Addr& other) const {
|
||||
if (ver != other.ver)
|
||||
throw ip_addr_version_inconsistency();
|
||||
switch (ver)
|
||||
{
|
||||
case V4:
|
||||
{
|
||||
Addr ret;
|
||||
ret.ver = V4;
|
||||
ret.u.v4 = u.v4 & other.u.v4;
|
||||
return ret;
|
||||
}
|
||||
case V6:
|
||||
{
|
||||
Addr ret;
|
||||
ret.ver = V6;
|
||||
ret.u.v6 = u.v6 & other.u.v6;
|
||||
return ret;
|
||||
}
|
||||
default:
|
||||
throw ip_addr_unspecified();
|
||||
}
|
||||
}
|
||||
|
||||
Addr operator|(const Addr& other) const {
|
||||
if (ver != other.ver)
|
||||
throw ip_addr_version_inconsistency();
|
||||
switch (ver)
|
||||
{
|
||||
case V4:
|
||||
{
|
||||
Addr ret;
|
||||
ret.ver = V4;
|
||||
ret.u.v4 = u.v4 | other.u.v4;
|
||||
return ret;
|
||||
}
|
||||
case V6:
|
||||
{
|
||||
Addr ret;
|
||||
ret.ver = V6;
|
||||
ret.u.v6 = u.v6 | other.u.v6;
|
||||
return ret;
|
||||
}
|
||||
default:
|
||||
throw ip_addr_unspecified();
|
||||
}
|
||||
}
|
||||
|
||||
void reset_ipv4_from_uint32(const IPv4::Addr::base_type addr)
|
||||
{
|
||||
ver = V4;
|
||||
u.v4 = IPv4::Addr::from_uint32(addr);
|
||||
}
|
||||
|
||||
bool unspecified() const
|
||||
{
|
||||
switch (ver)
|
||||
{
|
||||
case V4:
|
||||
return u.v4.unspecified();
|
||||
case V6:
|
||||
return u.v6.unspecified();
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
IPv4::Addr v4;
|
||||
IPv6::Addr v6;
|
||||
} u;
|
||||
|
||||
Version ver;
|
||||
};
|
||||
OPENVPN_OSTREAM(Addr, to_string)
|
||||
|
||||
struct AddrMaskPair
|
||||
{
|
||||
Addr addr;
|
||||
Addr netmask;
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
return addr.to_string() + "/" + netmask.to_string();
|
||||
}
|
||||
};
|
||||
OPENVPN_OSTREAM(AddrMaskPair, to_string)
|
||||
|
||||
}
|
||||
} // namespace openvpn
|
||||
|
||||
#endif // OPENVPN_ADDR_IP_H
|
||||
|
97
openvpn/addr/ipv4.hpp
Normal file
97
openvpn/addr/ipv4.hpp
Normal file
@ -0,0 +1,97 @@
|
||||
#ifndef OPENVPN_ADDR_IPV4_H
|
||||
#define OPENVPN_ADDR_IPV4_H
|
||||
|
||||
#include <boost/cstdint.hpp> // for boost::uint32_t
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/ostream.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
namespace IP {
|
||||
class Addr;
|
||||
}
|
||||
|
||||
namespace IPv4 {
|
||||
|
||||
OPENVPN_SIMPLE_EXCEPTION(ipv4_render_exception);
|
||||
OPENVPN_EXCEPTION(ipv4_parse_exception);
|
||||
|
||||
class Addr // NOTE: must be union-legal, so default constructor does not initialize
|
||||
{
|
||||
friend class IP::Addr;
|
||||
|
||||
public:
|
||||
typedef boost::uint32_t base_type;
|
||||
|
||||
static Addr from_uint32(const base_type addr)
|
||||
{
|
||||
Addr ret;
|
||||
ret.u.addr = addr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Addr from_string(const std::string& ipstr, const char *title = NULL)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
boost::asio::ip::address_v4 a = boost::asio::ip::address_v4::from_string(ipstr, ec);
|
||||
if (ec)
|
||||
{
|
||||
if (!title)
|
||||
title = "";
|
||||
OPENVPN_THROW(ipv4_parse_exception, "error parsing " << title << " IPv4 address '" << ipstr << "' : " << ec.message());
|
||||
}
|
||||
return from_asio(a);
|
||||
}
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
const boost::asio::ip::address_v4 a = to_asio();
|
||||
boost::system::error_code ec;
|
||||
std::string ret = a.to_string(ec);
|
||||
if (ec)
|
||||
throw ipv4_render_exception();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Addr from_asio(const boost::asio::ip::address_v4& asio_addr)
|
||||
{
|
||||
Addr ret;
|
||||
ret.u.addr = asio_addr.to_ulong();
|
||||
return ret;
|
||||
}
|
||||
|
||||
boost::asio::ip::address_v4 to_asio() const
|
||||
{
|
||||
return boost::asio::ip::address_v4(u.addr);
|
||||
}
|
||||
|
||||
Addr operator&(const Addr& other) const {
|
||||
Addr ret;
|
||||
ret.u.addr = u.addr & other.u.addr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Addr operator|(const Addr& other) const {
|
||||
Addr ret;
|
||||
ret.u.addr = u.addr | other.u.addr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool unspecified() const
|
||||
{
|
||||
return u.addr == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
boost::uint32_t addr;
|
||||
unsigned char bytes[4];
|
||||
} u;
|
||||
};
|
||||
|
||||
OPENVPN_OSTREAM(Addr, to_string)
|
||||
}
|
||||
} // namespace openvpn
|
||||
|
||||
#endif // OPENVPN_ADDR_IPV4_H
|
101
openvpn/addr/ipv6.hpp
Normal file
101
openvpn/addr/ipv6.hpp
Normal file
@ -0,0 +1,101 @@
|
||||
#ifndef OPENVPN_ADDR_IPV6_H
|
||||
#define OPENVPN_ADDR_IPV6_H
|
||||
|
||||
#include <cstring> // for std::memcpy
|
||||
|
||||
#include <boost/cstdint.hpp> // for boost::uint32_t
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/ostream.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
namespace IP {
|
||||
class Addr;
|
||||
}
|
||||
|
||||
namespace IPv6 {
|
||||
|
||||
OPENVPN_SIMPLE_EXCEPTION(ipv6_render_exception);
|
||||
OPENVPN_EXCEPTION(ipv6_parse_exception);
|
||||
|
||||
class Addr // NOTE: must be union-legal, so default constructor does not initialize
|
||||
{
|
||||
friend class IP::Addr;
|
||||
|
||||
public:
|
||||
static Addr from_string(const std::string& ipstr, const char *title = NULL)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
boost::asio::ip::address_v6 a = boost::asio::ip::address_v6::from_string(ipstr, ec);
|
||||
if (ec)
|
||||
{
|
||||
if (!title)
|
||||
title = "";
|
||||
OPENVPN_THROW(ipv6_parse_exception, "error parsing " << title << " IPv6 address '" << ipstr << "' : " << ec.message());
|
||||
}
|
||||
return from_asio(a);
|
||||
}
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
const boost::asio::ip::address_v6 a = to_asio();
|
||||
boost::system::error_code ec;
|
||||
std::string ret = a.to_string(ec);
|
||||
if (ec)
|
||||
throw ipv6_render_exception();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Addr from_asio(const boost::asio::ip::address_v6& asio_addr)
|
||||
{
|
||||
Addr ret;
|
||||
boost::asio::ip::address_v6::bytes_type bytes = asio_addr.to_bytes();
|
||||
ret.scope_id_ = asio_addr.scope_id();
|
||||
std::memcpy(ret.u.bytes, bytes.data(), 16);
|
||||
return ret;
|
||||
}
|
||||
|
||||
boost::asio::ip::address_v6 to_asio() const
|
||||
{
|
||||
boost::asio::ip::address_v6::bytes_type bytes;
|
||||
std::memcpy(bytes.data(), u.bytes, 16);
|
||||
return boost::asio::ip::address_v6(bytes, scope_id_);
|
||||
}
|
||||
|
||||
Addr operator&(const Addr& other) const {
|
||||
Addr ret;
|
||||
ret.scope_id_ = scope_id_;
|
||||
ret.u.u64[0] = u.u64[0] & other.u.u64[0];
|
||||
ret.u.u64[1] = u.u64[1] & other.u.u64[1];
|
||||
return ret;
|
||||
}
|
||||
|
||||
Addr operator|(const Addr& other) const {
|
||||
Addr ret;
|
||||
ret.scope_id_ = scope_id_;
|
||||
ret.u.u64[0] = u.u64[0] | other.u.u64[0];
|
||||
ret.u.u64[1] = u.u64[1] | other.u.u64[1];
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool unspecified() const
|
||||
{
|
||||
return u.u64[0] == 0 && u.u64[1] == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
boost::uint64_t u64[2];
|
||||
boost::uint32_t u32[4];
|
||||
unsigned char bytes[16];
|
||||
} u;
|
||||
|
||||
unsigned int scope_id_;
|
||||
};
|
||||
|
||||
OPENVPN_OSTREAM(Addr, to_string)
|
||||
}
|
||||
} // namespace openvpn
|
||||
|
||||
#endif // OPENVPN_ADDR_IPV6_H
|
50
openvpn/addr/macaddr.hpp
Normal file
50
openvpn/addr/macaddr.hpp
Normal file
@ -0,0 +1,50 @@
|
||||
#ifndef OPENVPN_ADDR_MACADDR_H
|
||||
#define OPENVPN_ADDR_MACADDR_H
|
||||
|
||||
#include <ostream>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/ostream.hpp>
|
||||
#include <openvpn/common/hexstr.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
class MACAddr {
|
||||
public:
|
||||
MACAddr()
|
||||
{
|
||||
std::memset(addr_, 0, sizeof(addr_));
|
||||
}
|
||||
|
||||
void reset(const unsigned char *addr)
|
||||
{
|
||||
std::memcpy(addr_, addr, sizeof(addr_));
|
||||
}
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
std::string ret;
|
||||
ret.reserve(sizeof(addr_)*3);
|
||||
size_t size = sizeof(addr_);
|
||||
const unsigned char *data = addr_;
|
||||
while (size--)
|
||||
{
|
||||
const unsigned char c = *data++;
|
||||
ret += render_hex_char(c >> 4);
|
||||
ret += render_hex_char(c & 0x0F);
|
||||
if (size)
|
||||
ret += ':';
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned char addr_[6];
|
||||
};
|
||||
|
||||
OPENVPN_OSTREAM(MACAddr, to_string)
|
||||
|
||||
} // namespace openvpn
|
||||
|
||||
#endif // OPENVPN_ADDR_MACADDR_H
|
17
openvpn/common/ostream.hpp
Normal file
17
openvpn/common/ostream.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef OPENVPN_COMMON_OSTREAM_H
|
||||
#define OPENVPN_COMMON_OSTREAM_H
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
#define OPENVPN_OSTREAM(TYPE, TO_STRING) \
|
||||
template <typename Elem, typename Traits> \
|
||||
std::basic_ostream<Elem, Traits>& operator<<( \
|
||||
std::basic_ostream<Elem, Traits>& os, const TYPE& addr) \
|
||||
{ \
|
||||
std::string s = addr.TO_STRING(); \
|
||||
os << s; \
|
||||
return os; \
|
||||
}
|
||||
|
||||
#endif // OPENVPN_COMMON_OSTREAM_H
|
7
openvpn/common/socktypes.hpp
Normal file
7
openvpn/common/socktypes.hpp
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef OPENVPN_COMMON_SOCKTYPES_H
|
||||
#define OPENVPN_COMMON_SOCKTYPES_H
|
||||
|
||||
// defines stuff like htonl, htons, etc.
|
||||
#include <boost/asio/detail/socket_types.hpp>
|
||||
|
||||
#endif // OPENVPN_COMMON_SOCKTYPES_H
|
@ -3,12 +3,22 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <openvpn/common/types.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
namespace string {
|
||||
inline int strcasecmp(const char *s1, const char *s2)
|
||||
{
|
||||
return ::strcasecmp(s1, s2);
|
||||
}
|
||||
|
||||
/* Like strncpy but makes sure dest is always null terminated */
|
||||
inline void strncpynt (char *dest, const char *src, size_t maxlen)
|
||||
{
|
||||
strncpy (dest, src, maxlen);
|
||||
if (maxlen > 0)
|
||||
dest[maxlen - 1] = 0;
|
||||
}
|
||||
} // namespace string
|
||||
} // namespace openvpn
|
||||
|
||||
|
@ -4,13 +4,14 @@
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/cstdint.hpp> // for boost::uint32_t
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
#include <openvpn/common/types.hpp>
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/log/log.hpp>
|
||||
#include <openvpn/common/circ_list.hpp>
|
||||
#include <openvpn/common/socktypes.hpp>
|
||||
#include <openvpn/log/log.hpp>
|
||||
#include <openvpn/time/time.hpp>
|
||||
#include <openvpn/buffer/buffer.hpp>
|
||||
|
||||
|
@ -37,7 +37,7 @@ namespace openvpn {
|
||||
|
||||
OPENVPN_EXCEPTION(route_error);
|
||||
|
||||
RouteListLinux(const OptionList& opt, const boost::asio::ip::address& server_addr_arg)
|
||||
RouteListLinux(const OptionList& opt, const IP::Addr& server_addr_arg)
|
||||
: stopped(false), rg_flags(0), did_redirect_gw(false), server_addr(server_addr_arg)
|
||||
{
|
||||
local_gateway = get_default_gateway();
|
||||
@ -46,7 +46,7 @@ namespace openvpn {
|
||||
{
|
||||
const Option& o = opt.get("route-gateway");
|
||||
o.exact_args(2);
|
||||
route_gateway = validate_ip_address("route-gateway", o[1]);
|
||||
route_gateway = IP::Addr::validate(o[1], "route-gateway");
|
||||
}
|
||||
|
||||
// do redirect-gateway
|
||||
@ -154,7 +154,7 @@ namespace openvpn {
|
||||
bool stopped;
|
||||
unsigned int rg_flags;
|
||||
bool did_redirect_gw;
|
||||
boost::asio::ip::address server_addr;
|
||||
IP::Addr server_addr;
|
||||
std::string route_gateway;
|
||||
std::string local_gateway;
|
||||
};
|
||||
|
246
openvpn/netconf/mac/gwv4.hpp
Normal file
246
openvpn/netconf/mac/gwv4.hpp
Normal file
@ -0,0 +1,246 @@
|
||||
#ifndef OPENVPN_NETCONF_MAC_GWV4_H
|
||||
#define OPENVPN_NETCONF_MAC_GWV4_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/route.h>
|
||||
#include <net/if_dl.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <algorithm> // for std::max
|
||||
|
||||
#include <boost/cstdint.hpp> // for boost::uint32_t
|
||||
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/hexstr.hpp>
|
||||
#include <openvpn/common/scoped_fd.hpp>
|
||||
#include <openvpn/common/scoped_ptr.hpp>
|
||||
#include <openvpn/common/socktypes.hpp>
|
||||
#include <openvpn/common/string.hpp>
|
||||
#include <openvpn/addr/ip.hpp>
|
||||
#include <openvpn/addr/macaddr.hpp>
|
||||
#include <openvpn/log/log.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
class MacGatewayInfoV4
|
||||
{
|
||||
struct rtmsg {
|
||||
struct rt_msghdr m_rtm;
|
||||
char m_space[512];
|
||||
};
|
||||
|
||||
# define OPENVPN_ROUNDUP(a) \
|
||||
((a) > 0 ? (1 + (((a) - 1) | (sizeof(boost::uint32_t) - 1))) : sizeof(boost::uint32_t))
|
||||
|
||||
# define OPENVPN_NEXTADDR(w, u) \
|
||||
if (rtm_addrs & (w)) { \
|
||||
l = OPENVPN_ROUNDUP(u.sa_len); \
|
||||
std::memmove(cp, &(u), l); \
|
||||
cp += l; \
|
||||
}
|
||||
|
||||
# define OPENVPN_ADVANCE(x, n) \
|
||||
(x += OPENVPN_ROUNDUP((n)->sa_len))
|
||||
|
||||
public:
|
||||
OPENVPN_EXCEPTION(route_gateway_error);
|
||||
|
||||
enum {
|
||||
ADDR_DEFINED = (1<<0), /* set if gateway.addr defined */
|
||||
NETMASK_DEFINED = (1<<1), /* set if gateway.netmask defined */
|
||||
HWADDR_DEFINED = (1<<2), /* set if hwaddr is defined */
|
||||
IFACE_DEFINED = (1<<3), /* set if iface is defined */
|
||||
};
|
||||
|
||||
MacGatewayInfoV4()
|
||||
: flags_(0)
|
||||
{
|
||||
struct rtmsg m_rtmsg;
|
||||
ScopedFD sockfd;
|
||||
int seq, l, pid, rtm_addrs, i;
|
||||
struct sockaddr so_dst, so_mask;
|
||||
char *cp = m_rtmsg.m_space;
|
||||
struct sockaddr *gate = NULL, *ifp = NULL, *sa;
|
||||
struct rt_msghdr *rtm_aux;
|
||||
|
||||
/* setup data to send to routing socket */
|
||||
pid = ::getpid();
|
||||
seq = 0;
|
||||
rtm_addrs = RTA_DST | RTA_NETMASK | RTA_IFP;
|
||||
|
||||
std::memset(&m_rtmsg, 0, sizeof(m_rtmsg));
|
||||
std::memset(&so_dst, 0, sizeof(so_dst));
|
||||
std::memset(&so_mask, 0, sizeof(so_mask));
|
||||
std::memset(&m_rtmsg.m_rtm, 0, sizeof(struct rt_msghdr));
|
||||
|
||||
m_rtmsg.m_rtm.rtm_type = RTM_GET;
|
||||
m_rtmsg.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY;
|
||||
m_rtmsg.m_rtm.rtm_version = RTM_VERSION;
|
||||
m_rtmsg.m_rtm.rtm_seq = ++seq;
|
||||
m_rtmsg.m_rtm.rtm_addrs = rtm_addrs;
|
||||
|
||||
so_dst.sa_family = AF_INET;
|
||||
so_dst.sa_len = sizeof(struct sockaddr_in);
|
||||
so_mask.sa_family = AF_INET;
|
||||
so_mask.sa_len = sizeof(struct sockaddr_in);
|
||||
|
||||
OPENVPN_NEXTADDR(RTA_DST, so_dst);
|
||||
OPENVPN_NEXTADDR(RTA_NETMASK, so_mask);
|
||||
|
||||
m_rtmsg.m_rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
|
||||
|
||||
/* transact with routing socket */
|
||||
sockfd.reset(socket(PF_ROUTE, SOCK_RAW, 0));
|
||||
if (!sockfd.defined())
|
||||
throw route_gateway_error("GDG: socket #1 failed");
|
||||
if (::write(sockfd(), (char *)&m_rtmsg, l) < 0)
|
||||
throw route_gateway_error("GDG: problem writing to routing socket");
|
||||
do {
|
||||
l = ::read(sockfd(), (char *)&m_rtmsg, sizeof(m_rtmsg));
|
||||
} while (l > 0 && (m_rtmsg.m_rtm.rtm_seq != seq || m_rtmsg.m_rtm.rtm_pid != pid));
|
||||
sockfd.close();
|
||||
|
||||
/* extract return data from routing socket */
|
||||
rtm_aux = &m_rtmsg.m_rtm;
|
||||
cp = ((char *)(rtm_aux + 1));
|
||||
if (rtm_aux->rtm_addrs)
|
||||
{
|
||||
for (i = 1; i; i <<= 1)
|
||||
{
|
||||
if (i & rtm_aux->rtm_addrs)
|
||||
{
|
||||
sa = (struct sockaddr *)cp;
|
||||
if (i == RTA_GATEWAY )
|
||||
gate = sa;
|
||||
else if (i == RTA_IFP)
|
||||
ifp = sa;
|
||||
OPENVPN_ADVANCE(cp, sa);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
/* get gateway addr and interface name */
|
||||
if (gate != NULL )
|
||||
{
|
||||
/* get default gateway addr */
|
||||
gateway_.addr.reset_ipv4_from_uint32(ntohl(((struct sockaddr_in *)gate)->sin_addr.s_addr));
|
||||
if (!gateway_.addr.unspecified())
|
||||
flags_ |= ADDR_DEFINED;
|
||||
|
||||
if (ifp)
|
||||
{
|
||||
/* get interface name */
|
||||
const struct sockaddr_dl *adl = (struct sockaddr_dl *) ifp;
|
||||
const size_t len = adl->sdl_nlen;
|
||||
if (len && len < sizeof(iface_))
|
||||
{
|
||||
std::memcpy (iface_, adl->sdl_data, len);
|
||||
iface_[len] = '\0';
|
||||
flags_ |= IFACE_DEFINED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* get netmask of interface that owns default gateway */
|
||||
if (flags_ & IFACE_DEFINED) {
|
||||
struct ifreq ifr;
|
||||
|
||||
sockfd.reset(socket(AF_INET, SOCK_DGRAM, 0));
|
||||
if (!sockfd.defined())
|
||||
throw route_gateway_error("GDG: socket #2 failed");
|
||||
|
||||
std::memset(&ifr, 0, sizeof(ifr));
|
||||
ifr.ifr_addr.sa_family = AF_INET;
|
||||
string::strncpynt(ifr.ifr_name, iface_, IFNAMSIZ);
|
||||
|
||||
if (::ioctl(sockfd(), SIOCGIFNETMASK, (char *)&ifr) < 0)
|
||||
throw route_gateway_error("GDG: ioctl #1 failed");
|
||||
sockfd.close();
|
||||
|
||||
gateway_.netmask.reset_ipv4_from_uint32(ntohl(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr));
|
||||
flags_ |= NETMASK_DEFINED;
|
||||
}
|
||||
|
||||
/* try to read MAC addr associated with interface that owns default gateway */
|
||||
if (flags_ & IFACE_DEFINED)
|
||||
{
|
||||
struct ifconf ifc;
|
||||
struct ifreq *ifr;
|
||||
const int bufsize = 4096;
|
||||
|
||||
ScopedPtr<char> buffer(new char[bufsize]);
|
||||
std::memset(buffer.get(), 0, bufsize);
|
||||
sockfd.reset(socket(AF_INET, SOCK_DGRAM, 0));
|
||||
if (!sockfd.defined())
|
||||
throw route_gateway_error("GDG: socket #3 failed");
|
||||
|
||||
ifc.ifc_len = bufsize;
|
||||
ifc.ifc_buf = buffer.get();
|
||||
|
||||
if (::ioctl(sockfd(), SIOCGIFCONF, (char *)&ifc) < 0)
|
||||
throw route_gateway_error("GDG: ioctl #2 failed");
|
||||
sockfd.close();
|
||||
|
||||
for (cp = buffer.get(); cp <= buffer.get() + ifc.ifc_len - sizeof(struct ifreq); )
|
||||
{
|
||||
ifr = (struct ifreq *)cp;
|
||||
const size_t len = sizeof(ifr->ifr_name) + std::max(sizeof(ifr->ifr_addr), size_t(ifr->ifr_addr.sa_len));
|
||||
if (!ifr->ifr_addr.sa_family)
|
||||
break;
|
||||
if (!::strncmp(ifr->ifr_name, iface_, IFNAMSIZ))
|
||||
{
|
||||
if (ifr->ifr_addr.sa_family == AF_LINK)
|
||||
{
|
||||
struct sockaddr_dl *sdl = (struct sockaddr_dl *)&ifr->ifr_addr;
|
||||
hwaddr_.reset((const unsigned char *)LLADDR(sdl));
|
||||
flags_ |= HWADDR_DEFINED;
|
||||
}
|
||||
}
|
||||
cp += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
# undef OPENVPN_ROUNDUP
|
||||
# undef OPENVPN_NEXTADDR
|
||||
# undef OPENVPN_ADVANCE
|
||||
|
||||
std::string info() const
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "GATEWAY";
|
||||
if (flags_ & ADDR_DEFINED)
|
||||
{
|
||||
os << " ADDR=" << gateway_.addr;
|
||||
if (flags_ & NETMASK_DEFINED)
|
||||
{
|
||||
os << '/' << gateway_.netmask;
|
||||
}
|
||||
}
|
||||
if (flags_ & IFACE_DEFINED)
|
||||
os << " IFACE=" << iface_;
|
||||
if (flags_ & HWADDR_DEFINED)
|
||||
os << " HWADDR=" << hwaddr_;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
unsigned int flags() const { return flags_; }
|
||||
const IP::Addr& gateway_addr() const { return gateway_.addr; }
|
||||
const IP::Addr& gateway_netmask() const { return gateway_.netmask; }
|
||||
std::string iface() const { return iface_; }
|
||||
const MACAddr& hwaddr() const { return hwaddr_; }
|
||||
|
||||
private:
|
||||
unsigned int flags_;
|
||||
IP::AddrMaskPair gateway_;
|
||||
char iface_[16];
|
||||
MACAddr hwaddr_;
|
||||
};
|
||||
|
||||
} // namespace openvpn
|
||||
|
||||
#endif // OPENVPN_NETCONF_MAC_GWV4_H
|
@ -1,11 +1,10 @@
|
||||
#ifndef OPENVPN_NETCONF_MAC_ROUTE_H
|
||||
#define OPENVPN_NETCONF_MAC_ROUTE_H
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <openvpn/common/rc.hpp>
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/options.hpp>
|
||||
@ -15,6 +14,7 @@
|
||||
#include <openvpn/common/hexstr.hpp>
|
||||
#include <openvpn/addr/ip.hpp>
|
||||
#include <openvpn/log/log.hpp>
|
||||
#include <openvpn/netconf/mac/gwv4.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
@ -37,7 +37,7 @@ namespace openvpn {
|
||||
|
||||
OPENVPN_EXCEPTION(route_error);
|
||||
|
||||
RouteListMac(const OptionList& opt, const boost::asio::ip::address& server_addr_arg)
|
||||
RouteListMac(const OptionList& opt, const IP::Addr& server_addr_arg)
|
||||
: stopped(false), rg_flags(0), did_redirect_gw(false), server_addr(server_addr_arg)
|
||||
{
|
||||
local_gateway = get_default_gateway();
|
||||
@ -46,7 +46,7 @@ namespace openvpn {
|
||||
{
|
||||
const Option& o = opt.get("route-gateway");
|
||||
o.exact_args(2);
|
||||
route_gateway = validate_ip_address("route-gateway", o[1]);
|
||||
route_gateway = IP::Addr::from_string(o[1], "route-gateway");
|
||||
}
|
||||
|
||||
// do redirect-gateway
|
||||
@ -69,9 +69,7 @@ namespace openvpn {
|
||||
}
|
||||
if (rg_flags & RG_ENABLE)
|
||||
{
|
||||
add_del_route(true, server_addr.to_string(), "255.255.255.255", local_gateway);
|
||||
add_del_route(true, "0.0.0.0", "128.0.0.0", route_gateway);
|
||||
add_del_route(true, "128.0.0.0", "128.0.0.0", route_gateway);
|
||||
add_del_reroute_gw_v4(true);
|
||||
did_redirect_gw = true;
|
||||
}
|
||||
}
|
||||
@ -83,9 +81,7 @@ namespace openvpn {
|
||||
{
|
||||
if (did_redirect_gw)
|
||||
{
|
||||
add_del_route(false, server_addr.to_string(), "255.255.255.255", local_gateway);
|
||||
add_del_route(false, "0.0.0.0", "128.0.0.0", route_gateway);
|
||||
add_del_route(false, "128.0.0.0", "128.0.0.0", route_gateway);
|
||||
add_del_reroute_gw_v4(false);
|
||||
did_redirect_gw = false;
|
||||
}
|
||||
stopped = true;
|
||||
@ -97,35 +93,47 @@ namespace openvpn {
|
||||
stop();
|
||||
}
|
||||
|
||||
static std::string get_default_gateway()
|
||||
static const IP::Addr& get_default_gateway()
|
||||
{
|
||||
return "10.10.0.1"; // fixme
|
||||
MacGatewayInfoV4 gw; // fixme: handle IPv6
|
||||
return gw.gateway_addr();
|
||||
}
|
||||
|
||||
private:
|
||||
int add_del_route(const bool add,
|
||||
const std::string& net,
|
||||
const std::string& mask,
|
||||
const std::string& gw)
|
||||
void add_del_reroute_gw_v4(const bool add)
|
||||
{
|
||||
std::ostringstream cmd;
|
||||
cmd << "/sbin/route";
|
||||
if (add)
|
||||
cmd << " add";
|
||||
else
|
||||
cmd << " delete";
|
||||
cmd << " -net " << net << ' ' << gw << ' ' << mask;
|
||||
const std::string cmd_str = cmd.str();
|
||||
OPENVPN_LOG(cmd_str);
|
||||
return ::system(cmd_str.c_str());
|
||||
const IP::Addr a_255_255_255_255 = IP::Addr::from_string("255.255.255.255");
|
||||
const IP::Addr a_0_0_0_0 = IP::Addr::from_string("0.0.0.0");
|
||||
const IP::Addr a_128_0_0_0 = IP::Addr::from_string("128.0.0.0");
|
||||
|
||||
add_del_route(add, server_addr, a_255_255_255_255, local_gateway);
|
||||
add_del_route(add, a_0_0_0_0, a_128_0_0_0, route_gateway);
|
||||
add_del_route(add, a_128_0_0_0, a_128_0_0_0, route_gateway);
|
||||
}
|
||||
|
||||
int add_del_route(const bool add,
|
||||
const IP::Addr& net,
|
||||
const IP::Addr& mask,
|
||||
const IP::Addr& gw)
|
||||
{
|
||||
std::ostringstream cmd;
|
||||
cmd << "/sbin/route";
|
||||
if (add)
|
||||
cmd << " add";
|
||||
else
|
||||
cmd << " delete";
|
||||
cmd << " -net " << net << ' ' << gw << ' ' << mask;
|
||||
const std::string cmd_str = cmd.str();
|
||||
OPENVPN_LOG(cmd_str);
|
||||
return ::system(cmd_str.c_str());
|
||||
}
|
||||
|
||||
bool stopped;
|
||||
unsigned int rg_flags;
|
||||
bool did_redirect_gw;
|
||||
boost::asio::ip::address server_addr;
|
||||
std::string route_gateway;
|
||||
std::string local_gateway;
|
||||
IP::Addr server_addr;
|
||||
IP::Addr route_gateway;
|
||||
IP::Addr local_gateway;
|
||||
};
|
||||
|
||||
} // namespace openvpn
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
#include <openvpn/common/socktypes.hpp>
|
||||
#include <openvpn/buffer/buffer.hpp>
|
||||
#include <openvpn/crypto/packet_id.hpp>
|
||||
#include <openvpn/reliable/relcommon.hpp>
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <openvpn/common/hexstr.hpp>
|
||||
#include <openvpn/common/options.hpp>
|
||||
#include <openvpn/common/mode.hpp>
|
||||
#include <openvpn/common/socktypes.hpp>
|
||||
#include <openvpn/log/log.hpp>
|
||||
#include <openvpn/buffer/buffer.hpp>
|
||||
#include <openvpn/time/time.hpp>
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/rc.hpp>
|
||||
#include <openvpn/addr/ip.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
@ -19,7 +20,7 @@ namespace openvpn {
|
||||
virtual bool transport_send_const(const Buffer& buf) = 0;
|
||||
virtual bool transport_send(BufferAllocated& buf) = 0;
|
||||
virtual std::string server_endpoint_render() const = 0;
|
||||
virtual boost::asio::ip::address server_endpoint_addr() const = 0;
|
||||
virtual IP::Addr server_endpoint_addr() const = 0;
|
||||
};
|
||||
|
||||
struct TransportClientParent
|
||||
|
@ -77,9 +77,9 @@ namespace openvpn {
|
||||
return os.str();
|
||||
}
|
||||
|
||||
virtual boost::asio::ip::address server_endpoint_addr() const
|
||||
virtual IP::Addr server_endpoint_addr() const
|
||||
{
|
||||
return server_endpoint.address();
|
||||
return IP::Addr::from_asio(server_endpoint.address());
|
||||
}
|
||||
|
||||
virtual void stop() { stop_(); }
|
||||
|
@ -15,7 +15,7 @@ namespace openvpn {
|
||||
|
||||
std::string name;
|
||||
bool ipv6;
|
||||
bool tap;
|
||||
Layer layer;
|
||||
int txqueuelen;
|
||||
unsigned int mtu;
|
||||
|
||||
@ -32,7 +32,7 @@ namespace openvpn {
|
||||
TunClientParent& parent);
|
||||
private:
|
||||
ClientConfig()
|
||||
: ipv6(false), tap(false), txqueuelen(200), mtu(1500), n_parallel(8) {}
|
||||
: ipv6(false), txqueuelen(200), mtu(1500), n_parallel(8) {}
|
||||
};
|
||||
|
||||
class Client : public TunClient
|
||||
@ -56,7 +56,7 @@ namespace openvpn {
|
||||
config->stats,
|
||||
config->name,
|
||||
config->ipv6,
|
||||
config->tap,
|
||||
config->layer,
|
||||
config->txqueuelen
|
||||
));
|
||||
impl->start(config->n_parallel);
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <openvpn/log/protostats.hpp>
|
||||
#include <openvpn/tun/tunspec.hpp>
|
||||
#include <openvpn/tun/tunlog.hpp>
|
||||
#include <openvpn/tun/layer.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
namespace TunLinux {
|
||||
@ -36,6 +37,7 @@ namespace openvpn {
|
||||
|
||||
// exceptions
|
||||
OPENVPN_EXCEPTION(tun_open_error);
|
||||
OPENVPN_EXCEPTION(tun_layer_error);
|
||||
OPENVPN_EXCEPTION(tun_ioctl_error);
|
||||
OPENVPN_EXCEPTION(tun_fcntl_error);
|
||||
OPENVPN_EXCEPTION(tun_name_error);
|
||||
@ -53,7 +55,7 @@ namespace openvpn {
|
||||
const ProtoStats::Ptr& stats_arg,
|
||||
const std::string name,
|
||||
const bool ipv6,
|
||||
const bool tap,
|
||||
const Layer& layer,
|
||||
const int txqueuelen)
|
||||
|
||||
: halt(false),
|
||||
@ -71,10 +73,12 @@ namespace openvpn {
|
||||
ifr.ifr_flags = IFF_ONE_QUEUE;
|
||||
if (!ipv6)
|
||||
ifr.ifr_flags |= IFF_NO_PI;
|
||||
if (tap)
|
||||
if (layer() == Layer::OSI_LAYER_3)
|
||||
ifr.ifr_flags |= IFF_TUN;
|
||||
else if (layer() == Layer::OSI_LAYER_2)
|
||||
ifr.ifr_flags |= IFF_TAP;
|
||||
else
|
||||
ifr.ifr_flags |= IFF_TUN;
|
||||
throw tun_layer_error("unknown OSI layer");
|
||||
if (!name.empty())
|
||||
{
|
||||
if (name.length() < IFNAMSIZ)
|
||||
@ -172,8 +176,8 @@ namespace openvpn {
|
||||
{
|
||||
const Option& o = opt.get("ifconfig");
|
||||
o.exact_args(3);
|
||||
std::string ip = validate_ip_address("ifconfig-ip", o[1]);
|
||||
std::string mask = validate_ip_address("ifconfig-net", o[2]);
|
||||
std::string ip = IP::Addr::validate(o[1], "ifconfig-ip");
|
||||
std::string mask = IP::Addr::validate(o[2], "ifconfig-net");
|
||||
std::ostringstream cmd;
|
||||
cmd << "/sbin/ifconfig " << name() << ' ' << ip << " netmask " << mask << " mtu " << mtu;
|
||||
const std::string cmd_str = cmd.str();
|
||||
|
@ -13,7 +13,7 @@ namespace openvpn {
|
||||
public:
|
||||
typedef boost::intrusive_ptr<ClientConfig> Ptr;
|
||||
|
||||
bool tap;
|
||||
Layer layer;
|
||||
unsigned int mtu;
|
||||
|
||||
int n_parallel;
|
||||
@ -29,7 +29,7 @@ namespace openvpn {
|
||||
TunClientParent& parent);
|
||||
private:
|
||||
ClientConfig()
|
||||
: tap(false), mtu(1500), n_parallel(8) {}
|
||||
: mtu(1500), n_parallel(8) {}
|
||||
};
|
||||
|
||||
class Client : public TunClient
|
||||
@ -51,7 +51,7 @@ namespace openvpn {
|
||||
this,
|
||||
config->frame,
|
||||
config->stats,
|
||||
config->tap
|
||||
config->layer
|
||||
));
|
||||
impl->start(config->n_parallel);
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <openvpn/log/protostats.hpp>
|
||||
#include <openvpn/tun/tunspec.hpp>
|
||||
#include <openvpn/tun/tunlog.hpp>
|
||||
#include <openvpn/tun/layer.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
namespace TunMac {
|
||||
@ -33,6 +34,7 @@ namespace openvpn {
|
||||
|
||||
// exceptions
|
||||
OPENVPN_EXCEPTION(tun_open_error);
|
||||
OPENVPN_EXCEPTION(tun_layer_error);
|
||||
OPENVPN_EXCEPTION(tun_fcntl_error);
|
||||
|
||||
template <typename ReadHandler>
|
||||
@ -45,7 +47,7 @@ namespace openvpn {
|
||||
ReadHandler read_handler_arg,
|
||||
const Frame::Ptr& frame_arg,
|
||||
const ProtoStats::Ptr& stats_arg,
|
||||
const bool tap)
|
||||
const Layer& layer)
|
||||
|
||||
: halt(false),
|
||||
read_handler(read_handler_arg),
|
||||
@ -55,10 +57,12 @@ namespace openvpn {
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
std::ostringstream node;
|
||||
if (tap)
|
||||
if (layer() == Layer::OSI_LAYER_3)
|
||||
node << "tun";
|
||||
else if (layer() == Layer::OSI_LAYER_2)
|
||||
node << "tap";
|
||||
else
|
||||
node << "tun";
|
||||
throw tun_layer_error("unknown OSI layer");
|
||||
node << i;
|
||||
const std::string node_str = node.str();
|
||||
const std::string node_fn = "/dev/" + node_str;
|
||||
@ -77,7 +81,7 @@ namespace openvpn {
|
||||
}
|
||||
}
|
||||
|
||||
OPENVPN_THROW(tun_open_error, "error opening Mac " << (tap ? "tap" : "tun") << " device");
|
||||
OPENVPN_THROW(tun_open_error, "error opening Mac " << layer.dev_type() << " device");
|
||||
}
|
||||
|
||||
bool write(const Buffer& buf)
|
||||
@ -128,6 +132,8 @@ namespace openvpn {
|
||||
|
||||
int ifconfig(const OptionList& opt, const unsigned int mtu) // fixme -- support IPv6
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
// first verify topology
|
||||
{
|
||||
const Option& o = opt.get("topology");
|
||||
@ -140,24 +146,26 @@ namespace openvpn {
|
||||
{
|
||||
const Option& o = opt.get("ifconfig");
|
||||
o.exact_args(3);
|
||||
std::string ip = validate_ip_address("ifconfig-ip", o[1]);
|
||||
std::string mask = validate_ip_address("ifconfig-net", o[2]);
|
||||
const IP::Addr ip = IP::Addr::from_string(o[1], "ifconfig-ip");
|
||||
const IP::Addr mask = IP::Addr::from_string(o[2], "ifconfig-net");
|
||||
{
|
||||
std::ostringstream cmd;
|
||||
cmd << "/sbin/ifconfig " << name() << ' ' << ip << ' ' << ip << " netmask " << mask << " mtu " << mtu << " up";
|
||||
const std::string cmd_str = cmd.str();
|
||||
OPENVPN_LOG_TUN(cmd_str);
|
||||
const int status = ::system(cmd_str.c_str());
|
||||
}
|
||||
{
|
||||
std::ostringstream cmd;
|
||||
cmd << "/sbin/route add -net 5.5.8.0 " << ip << ' ' << mask; // fixme
|
||||
const std::string cmd_str = cmd.str();
|
||||
OPENVPN_LOG_TUN(cmd_str);
|
||||
const int status = ::system(cmd_str.c_str());
|
||||
status = ::system(cmd_str.c_str());
|
||||
}
|
||||
if (!status)
|
||||
{
|
||||
std::ostringstream cmd;
|
||||
const IP::Addr net = ip & mask;
|
||||
cmd << "/sbin/route add -net " << net << ' ' << ip << ' ' << mask;
|
||||
const std::string cmd_str = cmd.str();
|
||||
OPENVPN_LOG_TUN(cmd_str);
|
||||
status = ::system(cmd_str.c_str());
|
||||
}
|
||||
}
|
||||
return 0; // fixme -- maybe return system() status
|
||||
return status;
|
||||
}
|
||||
|
||||
~Tun() { stop(); }
|
||||
@ -193,7 +201,6 @@ namespace openvpn {
|
||||
}
|
||||
else
|
||||
{
|
||||
::sleep(1);
|
||||
OPENVPN_LOG_TUN_ERROR("TUN Read Error: " << error);
|
||||
stats->error(ProtoStats::TUN_ERROR);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user