1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 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- OpenVPN Inc.
//
// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
//
// 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;
};
} // namespace openvpn
#endif
|