123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- /* vim: set expandtab ts=4 sw=4: */
- /*
- * You may redistribute this program and/or modify it under the terms of
- * the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- #define _WIN32_WINNT 0x0600
- #include "exception/WinEr.h"
- #include "util/platform/netdev/NetPlatform.h"
- #include "util/Bits.h"
- #include "util/platform/Sockaddr.h"
- #include <winsock2.h>
- #include <windows.h>
- #define NET_LUID misalligned_NET_LUID
- #define PNET_LUID misalligned_PNET_LUID
- #define IF_LUID misalligned_IF_LUID
- #define PIF_LUID misalligned_PIF_LUID
- #include <ifdef.h>
- #undef NET_LUID
- #undef PNET_LUID
- #undef IF_LUID
- #undef PIF_LUID
- // mingw-w64 incorrectly pragma pack's this to 1 byte.
- typedef union NET_LUID {
- ULONG64 Value;
- __C89_NAMELESS struct { /* bitfield with 64 bit types. */
- ULONG64 Reserved :24;
- ULONG64 NetLuidIndex :24;
- ULONG64 IfType :16;
- } Info;
- } NET_LUID, *PNET_LUID;
- Assert_compileTime(sizeof(NET_LUID) == 8);
- typedef NET_LUID IF_LUID, *PIF_LUID;
- #include <ws2ipdef.h>
- #include <naptypes.h>
- #include <ntddndis.h>
- #include <string.h>
- #include <ws2def.h>
- #include <iprtrmib.h>
- #include <ifdef.h>
- #include <iphlpapi.h>
- static Er_DEFUN(NET_LUID getLuid(const char* name, struct Allocator* alloc))
- {
- uint16_t ifName[IF_MAX_STRING_SIZE + 1] = {0};
- WinEr_check(alloc,
- (!MultiByteToWideChar(CP_ACP, 0, name, strlen(name), ifName, IF_MAX_STRING_SIZE + 1))
- );
- NET_LUID out;
- WinEr_check(alloc, ConvertInterfaceAliasToLuid(ifName, &out));
- Er_ret(out);
- }
- static LONG flushAddresses(NET_LUID luid, MIB_UNICASTIPADDRESS_TABLE* table)
- {
- LONG out = NO_ERROR;
- for (int i = 0; i < (int)table->NumEntries; i++) {
- if (table->Table[i].InterfaceLuid.Value == luid.Value) {
- if ((out = DeleteUnicastIpAddressEntry(&table->Table[i]))) {
- return out;
- }
- }
- }
- return out;
- }
- Er_DEFUN(void NetPlatform_flushAddresses(const char* deviceName, struct Allocator* alloc))
- {
- NET_LUID luid = Er(getLuid(deviceName, alloc));
- MIB_UNICASTIPADDRESS_TABLE* table;
- WinEr_check(alloc, GetUnicastIpAddressTable(AF_INET, &table));
- LONG ret = flushAddresses(luid, table);
- FreeMibTable(table);
- if (ret) {
- WinEr_fail(alloc, "DeleteUnicastIpAddressEntry(&table->Table[i])", ret);
- }
- WinEr_check(alloc, GetUnicastIpAddressTable(AF_INET6, &table));
- ret = flushAddresses(luid, table);
- FreeMibTable(table);
- if (ret) {
- WinEr_fail(alloc, "DeleteUnicastIpAddressEntry(&table->Table[i])", ret);
- }
- Er_ret();
- }
- #include "util/Hex.h"
- #include <stdio.h>
- static Er_DEFUN(void setupRoute(const char* deviceName,
- const uint8_t* addrBytes,
- int prefixLen,
- int addrFam,
- struct Allocator* alloc))
- {
- void WINAPI InitializeIpForwardEntry(PMIB_IPFORWARD_ROW2 Row);
- MIB_IPFORWARD_ROW2 row = {
- .InterfaceLuid = Er(getLuid(deviceName, alloc)),
- .ValidLifetime = WSA_INFINITE,
- .PreferredLifetime = WSA_INFINITE,
- .Metric = 0xffffffff,
- .Protocol = MIB_IPPROTO_NETMGMT,
- .SitePrefixLength = 255,
- .DestinationPrefix = {
- .PrefixLength = prefixLen,
- .Prefix = { .si_family = addrFam }
- },
- .NextHop = { .si_family = addrFam },
- .Loopback = false,
- .AutoconfigureAddress = false,
- .Immortal = false,
- .Age = 0,
- .Origin = 0
- };
- if (addrFam == AF_INET6) {
- Bits_memcpy(&row.DestinationPrefix.Prefix.Ipv6.sin6_addr, addrBytes, 15);
- row.DestinationPrefix.Prefix.Ipv6.sin6_family = AF_INET6;
- // set the gateway addr to the client's addr +1
- uint64_t addr[2];
- Bits_memcpy(addr, addrBytes, 16);
- addr[1] = Endian_hostToBigEndian64(Endian_bigEndianToHost64(addr[1]) + 1);
- if (!addr[1]) {
- addr[0] = Endian_hostToBigEndian64(Endian_bigEndianToHost64(addr[0]) + 1);
- }
- // Bits_memcpy(&row.NextHop.Ipv6.sin6_addr, addr, 16);
- } else {
- Bits_memcpy(&row.DestinationPrefix.Prefix.Ipv4.sin_addr, addrBytes, 4);
- row.DestinationPrefix.Prefix.Ipv4.sin_family = AF_INET;
- uint32_t addr;
- Bits_memcpy(&addr, addrBytes, 4);
- addr = Endian_hostToBigEndian32(Endian_bigEndianToHost32(addr) + 1);
- Bits_memcpy(&row.NextHop.Ipv4.sin_addr, &addr, 4);
- }
- //InitializeIpForwardEntry(&row);
- uint8_t buff[sizeof(row) * 2 + 1];
- Hex_encode(buff, sizeof(buff), (uint8_t*) &row, sizeof(row));
- printf("%s %d\n", buff, row.SitePrefixLength);
- // Hex_encode(buff, sizeof(buff), (uint8_t*) &row, sizeof(row));
- // printf("%s %d<\n", buff, row.SitePrefixLength);
- WinEr_check(alloc, CreateIpForwardEntry2(&row));
- Er_ret();
- }
- Er_DEFUN(void NetPlatform_addAddress(const char* interfaceName,
- const uint8_t* address,
- int prefixLen,
- int addrFam,
- struct Log* logger,
- struct Allocator* tempAlloc))
- {
- MIB_UNICASTIPADDRESS_ROW ipRow = {
- .PrefixOrigin = IpPrefixOriginUnchanged,
- .SuffixOrigin = IpSuffixOriginUnchanged,
- .ValidLifetime = 0xFFFFFFFF,
- .PreferredLifetime = 0xFFFFFFFF,
- .OnLinkPrefixLength = 0xFF
- };
- ipRow.InterfaceLuid = Er(getLuid(interfaceName, tempAlloc));
- ipRow.Address.si_family = addrFam;
- if (addrFam == Sockaddr_AF_INET6) {
- Bits_memcpy(&ipRow.Address.Ipv6.sin6_addr, address, 16);
- } else if (addrFam == Sockaddr_AF_INET) {
- Bits_memcpy(&ipRow.Address.Ipv4.sin_addr, address, 4);
- } else {
- Assert_true(0);
- }
- ipRow.OnLinkPrefixLength = prefixLen;
- WinEr_check(tempAlloc, CreateUnicastIpAddressEntry(&ipRow));
- if (0) {
- // setupRoute was disabled in d7f5b302ac9215221428de81b9a496b40dcb3884
- Er(setupRoute(interfaceName, address, prefixLen, addrFam, tempAlloc));
- }
- Er_ret();
- }
- Er_DEFUN(void NetPlatform_setMTU(const char* interfaceName,
- uint32_t mtu,
- struct Log* logger,
- struct Allocator* errAlloc))
- {
- // I looked all through the Windows API and setting the MTU is beyond me.
- // But I do know how to do it through netsh.
- // We know the connection names on Windows can't have any badly-behaved
- // characters that would need escaping.
- const char* format = ("netsh interface ipv6 set subinterface "
- "\"%s\" mtu=%d");
- // How much space do we need to fit the pattern substituted with the
- // interface name? We ought to use _vscprintf, but the compiler chokes on
- // its variable arguiment list. For now we overestimate: pattern length +
- // interrface name length + estimated size of the MTU number according to
- // <http://stackoverflow.com/a/3920025/402891> + a byte for the null
- // terminator.
- uint32_t totalSize = strlen(format) + strlen(interfaceName) +
- (CHAR_BIT * sizeof(uint32_t)) / 3 + 3 + 1;
- // Make a buffer to prepare our command in
- char buffer[totalSize];
- // Fill in the interface name
- snprintf(buffer, totalSize, format, interfaceName, mtu);
- Log_debug(logger, "Going to run command: %s", buffer);
- // Make the netsh call, and die if it returns the wrong thing.
- WinEr_check(errAlloc, system(buffer));
- // We should also configure the MTU for ipv4 (IpTunnel) case
- const char* format1 = ("netsh interface ipv4 set subinterface "
- "\"%s\" mtu=%d");
- snprintf(buffer, totalSize, format1, interfaceName, mtu);
- Log_debug(logger, "Going to run command: %s", buffer);
- WinEr_check(errAlloc, system(buffer));
- Er_ret();
- }
- Er_DEFUN(void NetPlatform_setRoutes(const char* ifName,
- struct Sockaddr** prefixSet,
- int prefixCount,
- struct Log* logger,
- struct Allocator* tempAlloc))
- {
- Er_raise(tempAlloc, "NetPlatform_setRoutes is not implemented in this platform.");
- }
|