File: enumiface.hpp

package info (click to toggle)
openvpn3-client 25%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 19,276 kB
  • sloc: cpp: 190,085; python: 7,218; ansic: 1,866; sh: 1,361; java: 402; lisp: 81; makefile: 17
file content (211 lines) | stat: -rw-r--r-- 5,774 bytes parent folder | download
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