File: netutil.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 (134 lines) | stat: -rw-r--r-- 3,707 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
//    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) 2024- OpenVPN Inc.
//
//    SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
//


// Windows network related utilities

#pragma once

#include <string>
#include "openvpn/win/reg.hpp"

namespace openvpn::Win {

struct NetApi
{
    /**
     * Get the string interface UUID (with braces) for an interface alias name
     *
     * @param  itf_name         the interface alias name
     * @return std::wstring     the wide IID string
     */
    static std::wstring get_itf_id(const std::string &itf_name)
    {
        DWORD err;
        NET_LUID luid;
        err = ::ConvertInterfaceAliasToLuid(wstring::from_utf8(itf_name).c_str(), &luid);
        if (err)
            return {};

        IID guid;
        err = ::ConvertInterfaceLuidToGuid(&luid, &guid);
        if (err)
            return {};

        PWSTR iid_str;
        if (::StringFromIID(guid, &iid_str) != S_OK)
            return {};

        std::wstring iid = iid_str;
        ::CoTaskMemFree(iid_str);
        return iid;
    }

    /**
     * @brief Check if an interface is connected and up
     *
     * @param  iid_str  the interface GUID string
     * @return bool     true if the interface is connected and up,
     *                  false otherwise or in case an error happened
     */
    static bool interface_connected(const std::wstring &iid_str)
    {
        GUID iid;
        MIB_IF_ROW2 itf_row;

        // Get LUID from GUID string
        if (::IIDFromString(iid_str.c_str(), &iid) != S_OK
            || ::ConvertInterfaceGuidToLuid(&iid, &itf_row.InterfaceLuid) != NO_ERROR)
        {
            return false;
        }

        // Look up interface status
        if (::GetIfEntry2(&itf_row) != NO_ERROR)
        {
            return false;
        }

        // Check if interface is connected and up
        if (itf_row.MediaConnectState != MediaConnectStateConnected
            || itf_row.OperStatus != IfOperStatusUp)
        {
            return false;
        }

        return true;
    }
};

/**
 * @brief Read interface specific domain suffix
 *
 * It can be either be the one assigned by DHCP or manually.
 *
 * @tparam REG          the Registry abstraction to use (default: Win::Reg)
 * @param  itf_guid     The interface GUID string
 * @return std::wstring The domain found, or the empty string
 */
template <typename REG = Win::Reg>
static std::wstring interface_dns_domain(const std::wstring &itf_guid)
{
    typename REG::Key itf_key(std::wstring(REG::subkey_ipv4_itfs) + L"\\" + itf_guid);

    auto [domain, error] = REG::get_string(itf_key, L"DhcpDomain");
    if (!error && !domain.empty())
    {
        return domain;
    }
    else
    {
        auto [domain, error] = REG::get_string(itf_key, L"Domain");
        if (!error && !domain.empty())
        {
            return domain;
        }
    }

    return {};
}

/**
 * @brief Checks if DHCP is enabled for an interface
 *
 * @tparam REG      the Registry abstraction to use (default: Win::Reg)
 * @param  itf_key  REG::Key of the interface to check for
 * @return bool     true if DHCP is enabled, false if
 *                  disabled or an error occurred
 */
template <typename REG = Win::Reg>
static bool dhcp_enabled_on_itf(typename REG::Key &itf_key)
{
    auto [dhcp, error] = REG::get_dword(itf_key, L"EnableDHCP");
    return !error && dhcp ? true : false;
}

} // namespace openvpn::Win