mirror of
https://github.com/deneraraujo/OpenVPNAdapter.git
synced 2026-04-06 00:00:03 +08:00
Merge commit '86cc97e55fe346502462284d2e636a2b3708163e' as 'Sources/OpenVPN3'
This commit is contained in:
218
Sources/OpenVPN3/openvpn/netconf/enumiface.hpp
Normal file
218
Sources/OpenVPN3/openvpn/netconf/enumiface.hpp
Normal file
@@ -0,0 +1,218 @@
|
||||
// OpenVPN -- An application to securely tunnel IP networks
|
||||
// over a single port, with support for SSL/TLS-based
|
||||
// session authentication and key exchange,
|
||||
// packet encryption, packet authentication, and
|
||||
// packet compression.
|
||||
//
|
||||
// Copyright (C) 2012-2017 OpenVPN Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License Version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program in the COPYING file.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Enumerate iOS network interfaces
|
||||
|
||||
#ifndef OPENVPN_NETCONF_ENUMIFACE_H
|
||||
#define OPENVPN_NETCONF_ENUMIFACE_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <ifaddrs.h>
|
||||
|
||||
#ifdef OPENVPN_PLATFORM_IPHONE
|
||||
#include <openvpn/netconf/ios/net-route.h>
|
||||
#else
|
||||
#include <net/route.h>
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
|
||||
#include <openvpn/common/size.hpp>
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/addr/ip.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
class EnumIface
|
||||
{
|
||||
public:
|
||||
OPENVPN_EXCEPTION(enum_iface_error);
|
||||
|
||||
EnumIface()
|
||||
: ifinfo(alloc_if_addrs(), free_if_addrs)
|
||||
{
|
||||
}
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "INTERFACES:" << std::endl;
|
||||
for (const ifaddrs* i = ifinfo.get(); i->ifa_next; i = i->ifa_next)
|
||||
render(i, os);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
bool iface_up(const char *iface) const
|
||||
{
|
||||
for (const ifaddrs* i = ifinfo.get(); i->ifa_next; i = i->ifa_next)
|
||||
{
|
||||
if (!std::strcmp(iface, i->ifa_name)
|
||||
&& (i->ifa_flags & RTF_UP)
|
||||
&& IP::Addr::sockaddr_defined(i->ifa_addr))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
static void render(const ifaddrs* i, std::ostream& os)
|
||||
{
|
||||
try {
|
||||
os << i->ifa_name;
|
||||
os << ' ' << render_flags(i->ifa_flags);
|
||||
if (i->ifa_addr)
|
||||
{
|
||||
const IP::Addr a = IP::Addr::from_sockaddr(i->ifa_addr);
|
||||
if (a.defined())
|
||||
os << ' ' << a;
|
||||
}
|
||||
if (i->ifa_netmask)
|
||||
{
|
||||
const IP::Addr nm = IP::Addr::from_sockaddr(i->ifa_netmask);
|
||||
if (nm.defined())
|
||||
{
|
||||
try {
|
||||
unsigned int pl = nm.prefix_len();
|
||||
os << '/' << pl;
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i->ifa_dstaddr)
|
||||
{
|
||||
const IP::Addr dst = IP::Addr::from_sockaddr(i->ifa_dstaddr);
|
||||
if (dst.defined())
|
||||
os << " (" << dst << ')';
|
||||
}
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
os << " ERROR";
|
||||
}
|
||||
os << std::endl;
|
||||
}
|
||||
|
||||
static std::string render_flags(const u_int flags)
|
||||
{
|
||||
struct flag_info {
|
||||
u_int flag;
|
||||
char c;
|
||||
};
|
||||
static const struct flag_info flag_info[] = {
|
||||
# ifdef RTF_UP
|
||||
{ RTF_UP, 'U' }, // Route usable
|
||||
# endif
|
||||
# ifdef RTF_GATEWAY
|
||||
{ RTF_GATEWAY, 'G' }, // Destination requires forwarding by intermediary
|
||||
# endif
|
||||
# ifdef RTF_HOST
|
||||
{ RTF_HOST, 'H' }, // Host entry (net otherwise)
|
||||
# endif
|
||||
# ifdef RTF_REJECT
|
||||
{ RTF_REJECT, 'R' }, // Host or net unreachable
|
||||
# endif
|
||||
# ifdef RTF_DYNAMIC
|
||||
{ RTF_DYNAMIC, 'D' }, // Created dynamically (by redirect)
|
||||
# endif
|
||||
# ifdef RTF_MODIFIED
|
||||
{ RTF_MODIFIED, 'M' }, // Modified dynamically (by redirect)
|
||||
# endif
|
||||
# ifdef RTF_CLONING
|
||||
{ RTF_CLONING, 'C' }, // Generate new routes on use
|
||||
# endif
|
||||
# ifdef RTF_XRESOLVE
|
||||
{ RTF_XRESOLVE, 'X' }, // External daemon translates proto to link address
|
||||
# endif
|
||||
# ifdef RTF_LLINFO
|
||||
{ RTF_LLINFO, 'L' }, // Valid protocol to link address translation
|
||||
# endif
|
||||
# ifdef RTF_STATIC
|
||||
{ RTF_STATIC, 'S' }, // Manually added
|
||||
# endif
|
||||
# ifdef RTF_BLACKHOLE
|
||||
{ RTF_BLACKHOLE, 'B' }, // Just discard packets (during updates)
|
||||
# endif
|
||||
# ifdef RTF_PROTO2
|
||||
{ RTF_PROTO2, '2' }, // Protocol specific routing flag #2
|
||||
# endif
|
||||
# ifdef RTF_PROTO1
|
||||
{ RTF_PROTO1, '1' }, // Protocol specific routing flag #1
|
||||
# endif
|
||||
# ifdef RTF_PRCLONING
|
||||
{ RTF_PRCLONING, 'c' }, // Protocol-specified generate new routes on use
|
||||
# endif
|
||||
# ifdef RTF_WASCLONED
|
||||
{ RTF_WASCLONED, 'W' }, // Route was generated as a result of cloning
|
||||
# endif
|
||||
# ifdef RTF_PROTO3
|
||||
{ RTF_PROTO3, '3' }, // Protocol specific routing flag #3
|
||||
# endif
|
||||
# ifdef RTF_BROADCAST
|
||||
{ RTF_BROADCAST, 'b' }, // The route represents a broadcast address
|
||||
# endif
|
||||
# ifdef RTF_MULTICAST
|
||||
{ RTF_MULTICAST, 'm' }, // The route represents a multicast address
|
||||
# endif
|
||||
# ifdef RTF_IFSCOPE
|
||||
{ RTF_IFSCOPE, 'I' }, // Route is associated with an interface scope
|
||||
# endif
|
||||
# ifdef RTF_IFREF
|
||||
{ RTF_IFREF, 'i' }, // Route is holding a reference to the interface
|
||||
# endif
|
||||
# ifdef RTF_PROXY
|
||||
{ RTF_PROXY, 'Y' }, // Proxying; cloned routes will not be scoped
|
||||
# endif
|
||||
# ifdef RTF_ROUTER
|
||||
{ RTF_ROUTER, 'r' }, // Host is a default router
|
||||
# endif
|
||||
{ 0, '\0' },
|
||||
};
|
||||
|
||||
std::string ret;
|
||||
for (const struct flag_info *fi = flag_info; fi->flag; ++fi)
|
||||
if (flags & fi->flag)
|
||||
ret += fi->c;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ifaddrs* alloc_if_addrs()
|
||||
{
|
||||
ifaddrs* ifa = nullptr;
|
||||
::getifaddrs(&ifa);
|
||||
return ifa;
|
||||
}
|
||||
|
||||
static void free_if_addrs(ifaddrs* p)
|
||||
{
|
||||
// delete method for pointer returned by getifaddrs
|
||||
freeifaddrs(p);
|
||||
}
|
||||
|
||||
std::unique_ptr<ifaddrs, decltype(&free_if_addrs)> ifinfo;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
74
Sources/OpenVPN3/openvpn/netconf/hwaddr.hpp
Normal file
74
Sources/OpenVPN3/openvpn/netconf/hwaddr.hpp
Normal file
@@ -0,0 +1,74 @@
|
||||
// OpenVPN -- An application to securely tunnel IP networks
|
||||
// over a single port, with support for SSL/TLS-based
|
||||
// session authentication and key exchange,
|
||||
// packet encryption, packet authentication, and
|
||||
// packet compression.
|
||||
//
|
||||
// Copyright (C) 2012-2017 OpenVPN Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License Version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program in the COPYING file.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Get the local MAC addr of the interface that owns the default route
|
||||
|
||||
#ifndef OPENVPN_NETCONF_HWADDR_H
|
||||
#define OPENVPN_NETCONF_HWADDR_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <openvpn/common/platform.hpp>
|
||||
#include <openvpn/addr/macaddr.hpp>
|
||||
|
||||
#if defined(OPENVPN_PLATFORM_WIN) && !defined(OPENVPN_PLATFORM_UWP)
|
||||
#include <openvpn/tun/win/tunutil.hpp>
|
||||
#elif defined(OPENVPN_PLATFORM_MAC)
|
||||
#include <openvpn/tun/mac/gwv4.hpp>
|
||||
#elif defined(TARGET_OS_IPHONE)
|
||||
#include <UIKit/UIKit.h>
|
||||
#endif
|
||||
|
||||
namespace openvpn {
|
||||
inline std::string get_hwaddr()
|
||||
{
|
||||
#if defined(OPENVPN_PLATFORM_WIN) && !defined(OPENVPN_PLATFORM_UWP)
|
||||
const TunWin::Util::DefaultGateway dg;
|
||||
if (dg.defined())
|
||||
{
|
||||
const TunWin::Util::IPAdaptersInfo ai_list;
|
||||
const IP_ADAPTER_INFO* ai = ai_list.adapter(dg.interface_index());
|
||||
if (ai)
|
||||
{
|
||||
const MACAddr mac(ai->Address);
|
||||
return mac.to_string();
|
||||
}
|
||||
}
|
||||
#elif defined(OPENVPN_PLATFORM_MAC)
|
||||
const MacGatewayInfoV4 gw;
|
||||
if (gw.hwaddr_defined())
|
||||
{
|
||||
const MACAddr& mac = gw.hwaddr();
|
||||
return mac.to_string();
|
||||
}
|
||||
#elif defined(TARGET_OS_IPHONE)
|
||||
// as reported at https://developer.apple.com/library/content/releasenotes/General/WhatsNewIniOS/Articles/iOS7.html#//apple_ref/doc/uid/TP40013162-SW34
|
||||
// we can't get the MAC address from iOS for privacy reasons, but we can
|
||||
// use the UUID as unique identifier. It is unique among the App domain,
|
||||
// meaning that a different app will get a different UUID from this call
|
||||
const NSString *uuid = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
|
||||
return std::string([uuid UTF8String]);
|
||||
#endif
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
248
Sources/OpenVPN3/openvpn/netconf/ios/net-route.h
Normal file
248
Sources/OpenVPN3/openvpn/netconf/ios/net-route.h
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2013 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. The rights granted to you under the License
|
||||
* may not be used to create, or enable the creation or redistribution of,
|
||||
* unlawful or unlicensed copies of an Apple operating system, or to
|
||||
* circumvent, violate, or enable the circumvention or violation of, any
|
||||
* terms of an Apple operating system software license agreement.
|
||||
*
|
||||
* Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1980, 1986, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)route.h 8.3 (Berkeley) 4/19/94
|
||||
* $FreeBSD: src/sys/net/route.h,v 1.36.2.1 2000/08/16 06:14:23 jayanth Exp $
|
||||
*/
|
||||
|
||||
#ifndef _NET_ROUTE_H_
|
||||
#define _NET_ROUTE_H_
|
||||
#include <sys/appleapiopts.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
/*
|
||||
* These numbers are used by reliable protocols for determining
|
||||
* retransmission behavior and are included in the routing structure.
|
||||
*/
|
||||
struct rt_metrics {
|
||||
u_int32_t rmx_locks; /* Kernel leaves these values alone */
|
||||
u_int32_t rmx_mtu; /* MTU for this path */
|
||||
u_int32_t rmx_hopcount; /* max hops expected */
|
||||
int32_t rmx_expire; /* lifetime for route, e.g. redirect */
|
||||
u_int32_t rmx_recvpipe; /* inbound delay-bandwidth product */
|
||||
u_int32_t rmx_sendpipe; /* outbound delay-bandwidth product */
|
||||
u_int32_t rmx_ssthresh; /* outbound gateway buffer limit */
|
||||
u_int32_t rmx_rtt; /* estimated round trip time */
|
||||
u_int32_t rmx_rttvar; /* estimated rtt variance */
|
||||
u_int32_t rmx_pksent; /* packets sent using this route */
|
||||
u_int32_t rmx_filler[4]; /* will be used for T/TCP later */
|
||||
};
|
||||
|
||||
/*
|
||||
* rmx_rtt and rmx_rttvar are stored as microseconds;
|
||||
*/
|
||||
#define RTM_RTTUNIT 1000000 /* units for rtt, rttvar, as units per sec */
|
||||
|
||||
|
||||
|
||||
#define RTF_UP 0x1 /* route usable */
|
||||
#define RTF_GATEWAY 0x2 /* destination is a gateway */
|
||||
#define RTF_HOST 0x4 /* host entry (net otherwise) */
|
||||
#define RTF_REJECT 0x8 /* host or net unreachable */
|
||||
#define RTF_DYNAMIC 0x10 /* created dynamically (by redirect) */
|
||||
#define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */
|
||||
#define RTF_DONE 0x40 /* message confirmed */
|
||||
#define RTF_DELCLONE 0x80 /* delete cloned route */
|
||||
#define RTF_CLONING 0x100 /* generate new routes on use */
|
||||
#define RTF_XRESOLVE 0x200 /* external daemon resolves name */
|
||||
#define RTF_LLINFO 0x400 /* generated by link layer (e.g. ARP) */
|
||||
#define RTF_STATIC 0x800 /* manually added */
|
||||
#define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */
|
||||
#define RTF_NOIFREF 0x2000 /* not eligible for RTF_IFREF */
|
||||
#define RTF_PROTO2 0x4000 /* protocol specific routing flag */
|
||||
#define RTF_PROTO1 0x8000 /* protocol specific routing flag */
|
||||
|
||||
#define RTF_PRCLONING 0x10000 /* protocol requires cloning */
|
||||
#define RTF_WASCLONED 0x20000 /* route generated through cloning */
|
||||
#define RTF_PROTO3 0x40000 /* protocol specific routing flag */
|
||||
/* 0x80000 unused */
|
||||
#define RTF_PINNED 0x100000 /* future use */
|
||||
#define RTF_LOCAL 0x200000 /* route represents a local address */
|
||||
#define RTF_BROADCAST 0x400000 /* route represents a bcast address */
|
||||
#define RTF_MULTICAST 0x800000 /* route represents a mcast address */
|
||||
#define RTF_IFSCOPE 0x1000000 /* has valid interface scope */
|
||||
#define RTF_CONDEMNED 0x2000000 /* defunct; no longer modifiable */
|
||||
#define RTF_IFREF 0x4000000 /* route holds a ref to interface */
|
||||
#define RTF_PROXY 0x8000000 /* proxying, no interface scope */
|
||||
#define RTF_ROUTER 0x10000000 /* host is a router */
|
||||
/* 0x20000000 and up unassigned */
|
||||
|
||||
#define RTF_BITS \
|
||||
"\020\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE" \
|
||||
"\10DELCLONE\11CLONING\12XRESOLVE\13LLINFO\14STATIC\15BLACKHOLE" \
|
||||
"\16NOIFREF\17PROTO2\20PROTO1\21PRCLONING\22WASCLONED\23PROTO3" \
|
||||
"\25PINNED\26LOCAL\27BROADCAST\30MULTICAST\31IFSCOPE\32CONDEMNED" \
|
||||
"\33IFREF\34PROXY\35ROUTER"
|
||||
|
||||
/*
|
||||
* Routing statistics.
|
||||
*/
|
||||
struct rtstat {
|
||||
short rts_badredirect; /* bogus redirect calls */
|
||||
short rts_dynamic; /* routes created by redirects */
|
||||
short rts_newgateway; /* routes modified by redirects */
|
||||
short rts_unreach; /* lookups which failed */
|
||||
short rts_wildcard; /* lookups satisfied by a wildcard */
|
||||
};
|
||||
|
||||
/*
|
||||
* Structures for routing messages.
|
||||
*/
|
||||
struct rt_msghdr {
|
||||
u_short rtm_msglen; /* to skip over non-understood messages */
|
||||
u_char rtm_version; /* future binary compatibility */
|
||||
u_char rtm_type; /* message type */
|
||||
u_short rtm_index; /* index for associated ifp */
|
||||
int rtm_flags; /* flags, incl. kern & message, e.g. DONE */
|
||||
int rtm_addrs; /* bitmask identifying sockaddrs in msg */
|
||||
pid_t rtm_pid; /* identify sender */
|
||||
int rtm_seq; /* for sender to identify action */
|
||||
int rtm_errno; /* why failed */
|
||||
int rtm_use; /* from rtentry */
|
||||
u_int32_t rtm_inits; /* which metrics we are initializing */
|
||||
struct rt_metrics rtm_rmx; /* metrics themselves */
|
||||
};
|
||||
|
||||
struct rt_msghdr2 {
|
||||
u_short rtm_msglen; /* to skip over non-understood messages */
|
||||
u_char rtm_version; /* future binary compatibility */
|
||||
u_char rtm_type; /* message type */
|
||||
u_short rtm_index; /* index for associated ifp */
|
||||
int rtm_flags; /* flags, incl. kern & message, e.g. DONE */
|
||||
int rtm_addrs; /* bitmask identifying sockaddrs in msg */
|
||||
int32_t rtm_refcnt; /* reference count */
|
||||
int rtm_parentflags; /* flags of the parent route */
|
||||
int rtm_reserved; /* reserved field set to 0 */
|
||||
int rtm_use; /* from rtentry */
|
||||
u_int32_t rtm_inits; /* which metrics we are initializing */
|
||||
struct rt_metrics rtm_rmx; /* metrics themselves */
|
||||
};
|
||||
|
||||
|
||||
#define RTM_VERSION 5 /* Up the ante and ignore older versions */
|
||||
|
||||
/*
|
||||
* Message types.
|
||||
*/
|
||||
#define RTM_ADD 0x1 /* Add Route */
|
||||
#define RTM_DELETE 0x2 /* Delete Route */
|
||||
#define RTM_CHANGE 0x3 /* Change Metrics or flags */
|
||||
#define RTM_GET 0x4 /* Report Metrics */
|
||||
#define RTM_LOSING 0x5 /* Kernel Suspects Partitioning */
|
||||
#define RTM_REDIRECT 0x6 /* Told to use different route */
|
||||
#define RTM_MISS 0x7 /* Lookup failed on this address */
|
||||
#define RTM_LOCK 0x8 /* fix specified metrics */
|
||||
#define RTM_OLDADD 0x9 /* caused by SIOCADDRT */
|
||||
#define RTM_OLDDEL 0xa /* caused by SIOCDELRT */
|
||||
#define RTM_RESOLVE 0xb /* req to resolve dst to LL addr */
|
||||
#define RTM_NEWADDR 0xc /* address being added to iface */
|
||||
#define RTM_DELADDR 0xd /* address being removed from iface */
|
||||
#define RTM_IFINFO 0xe /* iface going up/down etc. */
|
||||
#define RTM_NEWMADDR 0xf /* mcast group membership being added to if */
|
||||
#define RTM_DELMADDR 0x10 /* mcast group membership being deleted */
|
||||
#define RTM_IFINFO2 0x12 /* */
|
||||
#define RTM_NEWMADDR2 0x13 /* */
|
||||
#define RTM_GET2 0x14 /* */
|
||||
|
||||
/*
|
||||
* Bitmask values for rtm_inits and rmx_locks.
|
||||
*/
|
||||
#define RTV_MTU 0x1 /* init or lock _mtu */
|
||||
#define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */
|
||||
#define RTV_EXPIRE 0x4 /* init or lock _expire */
|
||||
#define RTV_RPIPE 0x8 /* init or lock _recvpipe */
|
||||
#define RTV_SPIPE 0x10 /* init or lock _sendpipe */
|
||||
#define RTV_SSTHRESH 0x20 /* init or lock _ssthresh */
|
||||
#define RTV_RTT 0x40 /* init or lock _rtt */
|
||||
#define RTV_RTTVAR 0x80 /* init or lock _rttvar */
|
||||
|
||||
/*
|
||||
* Bitmask values for rtm_addrs.
|
||||
*/
|
||||
#define RTA_DST 0x1 /* destination sockaddr present */
|
||||
#define RTA_GATEWAY 0x2 /* gateway sockaddr present */
|
||||
#define RTA_NETMASK 0x4 /* netmask sockaddr present */
|
||||
#define RTA_GENMASK 0x8 /* cloning mask sockaddr present */
|
||||
#define RTA_IFP 0x10 /* interface name sockaddr present */
|
||||
#define RTA_IFA 0x20 /* interface addr sockaddr present */
|
||||
#define RTA_AUTHOR 0x40 /* sockaddr for author of redirect */
|
||||
#define RTA_BRD 0x80 /* for NEWADDR, broadcast or p-p dest addr */
|
||||
|
||||
/*
|
||||
* Index offsets for sockaddr array for alternate internal encoding.
|
||||
*/
|
||||
#define RTAX_DST 0 /* destination sockaddr present */
|
||||
#define RTAX_GATEWAY 1 /* gateway sockaddr present */
|
||||
#define RTAX_NETMASK 2 /* netmask sockaddr present */
|
||||
#define RTAX_GENMASK 3 /* cloning mask sockaddr present */
|
||||
#define RTAX_IFP 4 /* interface name sockaddr present */
|
||||
#define RTAX_IFA 5 /* interface addr sockaddr present */
|
||||
#define RTAX_AUTHOR 6 /* sockaddr for author of redirect */
|
||||
#define RTAX_BRD 7 /* for NEWADDR, broadcast or p-p dest addr */
|
||||
#define RTAX_MAX 8 /* size of array to allocate */
|
||||
|
||||
struct rt_addrinfo {
|
||||
int rti_addrs;
|
||||
struct sockaddr *rti_info[RTAX_MAX];
|
||||
};
|
||||
|
||||
|
||||
#endif /* _NET_ROUTE_H_ */
|
||||
211
Sources/OpenVPN3/openvpn/netconf/linux/gw.hpp
Normal file
211
Sources/OpenVPN3/openvpn/netconf/linux/gw.hpp
Normal file
@@ -0,0 +1,211 @@
|
||||
// OpenVPN -- An application to securely tunnel IP networks
|
||||
// over a single port, with support for SSL/TLS-based
|
||||
// session authentication and key exchange,
|
||||
// packet encryption, packet authentication, and
|
||||
// packet compression.
|
||||
//
|
||||
// Copyright (C) 2012-2017 OpenVPN Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License Version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program in the COPYING file.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Find default gateways on Linux using ip route command
|
||||
|
||||
#ifndef OPENVPN_NETCONF_LINUX_GW_H
|
||||
#define OPENVPN_NETCONF_LINUX_GW_H
|
||||
|
||||
#include <string>
|
||||
#include <limits>
|
||||
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/number.hpp>
|
||||
#include <openvpn/common/split.hpp>
|
||||
#include <openvpn/common/splitlines.hpp>
|
||||
#include <openvpn/common/process.hpp>
|
||||
#include <openvpn/addr/route.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
class LinuxGW
|
||||
{
|
||||
public:
|
||||
OPENVPN_EXCEPTION(linux_gw_error);
|
||||
|
||||
LinuxGW(const std::string& ip_route_show_txt, const bool ignore_errors)
|
||||
{
|
||||
int best_metric = std::numeric_limits<int>::max();
|
||||
|
||||
SplitLines sl(ip_route_show_txt);
|
||||
while (sl())
|
||||
{
|
||||
const std::string& line = sl.line_ref();
|
||||
|
||||
try {
|
||||
// parse an output line generated by "ip [-6] route show"
|
||||
const std::vector<std::string> v = Split::by_space<std::vector<std::string>, NullLex, SpaceMatch, Split::NullLimit>(line);
|
||||
|
||||
// blank line?
|
||||
if (v.empty())
|
||||
continue;
|
||||
|
||||
// only interested in default routes
|
||||
if (v[0] != "default")
|
||||
continue;
|
||||
|
||||
// parse out route information
|
||||
enum RouteInfo {
|
||||
INITIAL,
|
||||
VIA,
|
||||
DEV,
|
||||
METRIC,
|
||||
};
|
||||
|
||||
std::string d;
|
||||
IP::Addr a;
|
||||
int m = std::numeric_limits<int>::max();
|
||||
|
||||
RouteInfo ri = INITIAL;
|
||||
for (const auto &term : v)
|
||||
{
|
||||
switch (ri)
|
||||
{
|
||||
case INITIAL:
|
||||
if (term == "via")
|
||||
ri = VIA;
|
||||
else if (term == "dev")
|
||||
ri = DEV;
|
||||
else if (term == "metric")
|
||||
ri = METRIC;
|
||||
else
|
||||
ri = INITIAL;
|
||||
break;
|
||||
case VIA:
|
||||
a = IP::Addr(term, "via");
|
||||
ri = INITIAL;
|
||||
break;
|
||||
case DEV:
|
||||
d = validate_dev(term);
|
||||
ri = INITIAL;
|
||||
break;
|
||||
case METRIC:
|
||||
m = parse_number_throw<int>(term, "bad metric");
|
||||
ri = INITIAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// best metric?
|
||||
if (m < best_metric || best_metric == std::numeric_limits<int>::max())
|
||||
{
|
||||
best_metric = m;
|
||||
dev_ = d;
|
||||
addr_ = a;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
if (!ignore_errors)
|
||||
OPENVPN_THROW(linux_gw_error, "error parsing line: " << line << " : " << e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::string ip_route_show(const bool ipv6)
|
||||
{
|
||||
RedirectPipe::InOut pipe;
|
||||
Argv argv;
|
||||
argv.emplace_back("/sbin/ip");
|
||||
if (ipv6)
|
||||
argv.emplace_back("-6");
|
||||
argv.emplace_back("route");
|
||||
argv.emplace_back("show");
|
||||
const int status = system_cmd(argv[0], argv, nullptr, pipe, 0);
|
||||
if (status != 0)
|
||||
OPENVPN_THROW(linux_gw_error, "command returned error status " << status << " : " << argv.to_string());
|
||||
return pipe.out;
|
||||
}
|
||||
|
||||
const std::string& dev() const
|
||||
{
|
||||
return dev_;
|
||||
}
|
||||
|
||||
const IP::Addr& addr() const
|
||||
{
|
||||
return addr_;
|
||||
}
|
||||
|
||||
bool defined() const
|
||||
{
|
||||
return !dev_.empty() && addr_.defined();
|
||||
}
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
return dev_ + '/' + addr_.to_string();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string validate_dev(const std::string& dev)
|
||||
{
|
||||
if (dev.empty())
|
||||
OPENVPN_THROW_EXCEPTION("dev is empty");
|
||||
return dev;
|
||||
}
|
||||
|
||||
std::string dev_;
|
||||
IP::Addr addr_;
|
||||
};
|
||||
|
||||
struct LinuxGW46
|
||||
{
|
||||
LinuxGW46(const bool ignore_errors)
|
||||
: v4(LinuxGW::ip_route_show(false), ignore_errors),
|
||||
v6(LinuxGW::ip_route_show(true), ignore_errors)
|
||||
{
|
||||
}
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
std::string ret = "[";
|
||||
if (v4.defined())
|
||||
{
|
||||
ret += "4:";
|
||||
ret += v4.to_string();
|
||||
}
|
||||
if (v6.defined())
|
||||
{
|
||||
if (v4.defined())
|
||||
ret += ' ';
|
||||
ret += "6:";
|
||||
ret += v6.to_string();
|
||||
}
|
||||
ret += "]";
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string dev() const
|
||||
{
|
||||
if (v4.defined())
|
||||
return v4.dev();
|
||||
else if (v6.defined())
|
||||
return v6.dev();
|
||||
else
|
||||
throw LinuxGW::linux_gw_error("cannot determine gateway interface");
|
||||
}
|
||||
|
||||
LinuxGW v4;
|
||||
LinuxGW v6;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
159
Sources/OpenVPN3/openvpn/netconf/linux/gwnetlink.hpp
Normal file
159
Sources/OpenVPN3/openvpn/netconf/linux/gwnetlink.hpp
Normal file
@@ -0,0 +1,159 @@
|
||||
// OpenVPN -- An application to securely tunnel IP networks
|
||||
// over a single port, with support for SSL/TLS-based
|
||||
// session authentication and key exchange,
|
||||
// packet encryption, packet authentication, and
|
||||
// packet compression.
|
||||
//
|
||||
// Copyright (C) 2012-2017 OpenVPN Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License Version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program in the COPYING file.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Find default gateways on Linux using ip route command
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/addr/ip.hpp>
|
||||
#include <openvpn/addr/ipv4.hpp>
|
||||
#include <openvpn/addr/ipv6.hpp>
|
||||
#include <openvpn/tun/linux/client/sitnl.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
class LinuxGWNetlink
|
||||
{
|
||||
public:
|
||||
OPENVPN_EXCEPTION(linux_gw_netlink_error);
|
||||
|
||||
/**
|
||||
* Provides gateway which is used to reach given address
|
||||
*
|
||||
* @param addr address which we want to reach
|
||||
* @param iface_to_ignore this allows to exclude certain interface
|
||||
* from discovered gateways. Used when we want to exclude VPN interface
|
||||
* when there is active VPN connection with redirected default gateway
|
||||
*
|
||||
* @param ipv6 true if address is IPv6
|
||||
*/
|
||||
LinuxGWNetlink(const std::string& addr, const std::string& iface_to_ignore, bool ipv6)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ipv6)
|
||||
{
|
||||
IPv6::Addr addr6;
|
||||
|
||||
if (TunNetlink::SITNL::net_route_best_gw(IP::Route6::from_string(addr),
|
||||
addr6, dev_, iface_to_ignore) < 0)
|
||||
{
|
||||
OPENVPN_THROW(linux_gw_netlink_error,
|
||||
"error retrieving default IPv6 GW");
|
||||
}
|
||||
|
||||
addr_ = IP::Addr::from_ipv6(addr6);
|
||||
}
|
||||
else
|
||||
{
|
||||
IPv4::Addr addr4;
|
||||
|
||||
if (TunNetlink::SITNL::net_route_best_gw(IP::Route4::from_string(addr),
|
||||
addr4, dev_, iface_to_ignore) < 0)
|
||||
{
|
||||
OPENVPN_THROW(linux_gw_netlink_error,
|
||||
"error retrieving default IPv4 GW");
|
||||
}
|
||||
|
||||
addr_ = IP::Addr::from_ipv4(addr4);
|
||||
}
|
||||
} catch (...)
|
||||
{
|
||||
/* nothing to do. just leave default GW unassigned */
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& dev() const
|
||||
{
|
||||
return dev_;
|
||||
}
|
||||
|
||||
const IP::Addr& addr() const
|
||||
{
|
||||
return addr_;
|
||||
}
|
||||
|
||||
bool defined() const
|
||||
{
|
||||
return !dev_.empty() && addr_.defined();
|
||||
}
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
return dev_ + '/' + addr_.to_string();
|
||||
}
|
||||
|
||||
private:
|
||||
IP::Addr addr_;
|
||||
std::string dev_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Provides IPv4/6 gateway which is used to reach given address
|
||||
*
|
||||
* @param iface_to_ignore this allows to exclude certain interface
|
||||
* from discovered gateways. Used when we want to exclude VPN interface
|
||||
* when there is active VPN connection with redirected default gateway
|
||||
* @param addr address which we want to reach
|
||||
*/
|
||||
struct LinuxGW46Netlink
|
||||
{
|
||||
LinuxGW46Netlink(const std::string& iface_to_ignore, const std::string& addr = "")
|
||||
: v4(addr.empty() ? IPv4::Addr::from_zero().to_string() : addr, iface_to_ignore, false),
|
||||
v6(addr.empty() ? IPv6::Addr::from_zero().to_string() : addr, iface_to_ignore, true)
|
||||
{
|
||||
}
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
std::string ret = "[";
|
||||
if (v4.defined())
|
||||
{
|
||||
ret += "4:";
|
||||
ret += v4.to_string();
|
||||
}
|
||||
if (v6.defined())
|
||||
{
|
||||
if (v4.defined())
|
||||
ret += ' ';
|
||||
ret += "6:";
|
||||
ret += v6.to_string();
|
||||
}
|
||||
ret += "]";
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string dev() const
|
||||
{
|
||||
if (v4.defined())
|
||||
return v4.dev();
|
||||
else if (v6.defined())
|
||||
return v6.dev();
|
||||
else
|
||||
throw LinuxGWNetlink::linux_gw_netlink_error("cannot determine gateway interface");
|
||||
}
|
||||
|
||||
LinuxGWNetlink v4;
|
||||
LinuxGWNetlink v6;
|
||||
};
|
||||
}
|
||||
160
Sources/OpenVPN3/openvpn/netconf/linux/route.hpp
Normal file
160
Sources/OpenVPN3/openvpn/netconf/linux/route.hpp
Normal file
@@ -0,0 +1,160 @@
|
||||
// OpenVPN -- An application to securely tunnel IP networks
|
||||
// over a single port, with support for SSL/TLS-based
|
||||
// session authentication and key exchange,
|
||||
// packet encryption, packet authentication, and
|
||||
// packet compression.
|
||||
//
|
||||
// Copyright (C) 2012-2017 OpenVPN Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License Version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program in the COPYING file.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Add routes on Linux using AF_NETLINK socket
|
||||
|
||||
#ifndef OPENVPN_NETCONF_LINUX_ROUTE_H
|
||||
#define OPENVPN_NETCONF_LINUX_ROUTE_H
|
||||
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <net/if.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/scoped_fd.hpp>
|
||||
#include <openvpn/common/strerror.hpp>
|
||||
#include <openvpn/addr/route.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
class LinuxRoute
|
||||
{
|
||||
public:
|
||||
OPENVPN_EXCEPTION(linux_route_error);
|
||||
|
||||
LinuxRoute()
|
||||
{
|
||||
fd.reset(::socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE));
|
||||
if (!fd.defined())
|
||||
throw linux_route_error("creating AF_NETLINK socket");
|
||||
|
||||
struct sockaddr_nl local;
|
||||
::memset(&local, 0, sizeof(local));
|
||||
local.nl_family = AF_NETLINK;
|
||||
local.nl_pad = 0;
|
||||
local.nl_pid = 0; // only use getpid() if unique instantiation per process
|
||||
local.nl_groups = 0;
|
||||
if (::bind(fd(), (struct sockaddr*)&local, sizeof(local)) < 0)
|
||||
throw linux_route_error("binding to AF_NETLINK socket");
|
||||
}
|
||||
|
||||
void add_delete(const bool add,
|
||||
const IP::Route& route,
|
||||
const int if_index,
|
||||
const int table=RT_TABLE_MAIN)
|
||||
{
|
||||
typedef struct {
|
||||
struct nlmsghdr nlmsg_info;
|
||||
struct rtmsg rtmsg_info;
|
||||
char buffer[64]; // must be large enough to contain request
|
||||
} netlink_req_t;
|
||||
|
||||
struct rtattr *rtattr_ptr;
|
||||
int rtmsg_len;
|
||||
struct sockaddr_nl peer;
|
||||
struct msghdr msg_info;
|
||||
struct iovec iov_info;
|
||||
netlink_req_t netlink_req;
|
||||
|
||||
::memset(&peer, 0, sizeof(peer));
|
||||
peer.nl_family = AF_NETLINK;
|
||||
peer.nl_pad = 0;
|
||||
peer.nl_pid = 0;
|
||||
peer.nl_groups = 0;
|
||||
|
||||
::memset(&msg_info, 0, sizeof(msg_info));
|
||||
msg_info.msg_name = (void *) &peer;
|
||||
msg_info.msg_namelen = sizeof(peer);
|
||||
|
||||
::memset(&netlink_req, 0, sizeof(netlink_req));
|
||||
|
||||
rtmsg_len = sizeof(struct rtmsg);
|
||||
|
||||
// add destination addr
|
||||
rtattr_ptr = (struct rtattr *) netlink_req.buffer;
|
||||
rtattr_ptr->rta_type = RTA_DST;
|
||||
rtattr_ptr->rta_len = sizeof(struct rtattr) + route.addr.size_bytes();
|
||||
route.addr.to_byte_string_variable(((unsigned char *)rtattr_ptr) + sizeof(struct rtattr));
|
||||
rtmsg_len += rtattr_ptr->rta_len;
|
||||
|
||||
// add if_index
|
||||
rtattr_ptr = (struct rtattr *) (((unsigned char *)rtattr_ptr) + rtattr_ptr->rta_len);
|
||||
rtattr_ptr->rta_type = RTA_OIF;
|
||||
rtattr_ptr->rta_len = sizeof(struct rtattr) + 4;
|
||||
::memcpy(((unsigned char *)rtattr_ptr) + sizeof(struct rtattr), &if_index, 4);
|
||||
rtmsg_len += rtattr_ptr->rta_len;
|
||||
|
||||
netlink_req.nlmsg_info.nlmsg_len = NLMSG_LENGTH(rtmsg_len);
|
||||
|
||||
if (add)
|
||||
{
|
||||
netlink_req.nlmsg_info.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
|
||||
netlink_req.nlmsg_info.nlmsg_type = RTM_NEWROUTE;
|
||||
}
|
||||
else // delete
|
||||
{
|
||||
netlink_req.nlmsg_info.nlmsg_flags = NLM_F_REQUEST;
|
||||
netlink_req.nlmsg_info.nlmsg_type = RTM_DELROUTE;
|
||||
}
|
||||
|
||||
netlink_req.rtmsg_info.rtm_family = route.addr.family();
|
||||
netlink_req.rtmsg_info.rtm_table = table;
|
||||
netlink_req.rtmsg_info.rtm_dst_len = route.prefix_len; // add prefix
|
||||
|
||||
netlink_req.rtmsg_info.rtm_protocol = RTPROT_STATIC;
|
||||
netlink_req.rtmsg_info.rtm_scope = RT_SCOPE_UNIVERSE;
|
||||
netlink_req.rtmsg_info.rtm_type = RTN_UNICAST;
|
||||
|
||||
iov_info.iov_base = (void *) &netlink_req.nlmsg_info;
|
||||
iov_info.iov_len = netlink_req.nlmsg_info.nlmsg_len;
|
||||
msg_info.msg_iov = &iov_info;
|
||||
msg_info.msg_iovlen = 1;
|
||||
|
||||
const ssize_t status = ::sendmsg(fd(), &msg_info, 0);
|
||||
if (status < 0)
|
||||
{
|
||||
const int eno = errno;
|
||||
OPENVPN_THROW(linux_route_error, "add_delete: sendmsg failed: " << strerror_str(eno));
|
||||
}
|
||||
}
|
||||
|
||||
static int if_index(const std::string& iface)
|
||||
{
|
||||
const unsigned int ret = ::if_nametoindex(iface.c_str());
|
||||
if (!ret)
|
||||
OPENVPN_THROW(linux_route_error, "if_index: no such interface: " << iface);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
ScopedFD fd;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user