Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
021474cdd2 | ||
|
|
308cd0dd00 | ||
|
|
83360d775b | ||
|
|
cdbaa0aff3 | ||
|
|
36ea86faaa | ||
|
|
8590a0813b | ||
|
|
51ae1c8770 |
+1
-1
Submodule GS-IPv6-Forwarder updated: d2b927c7b1...665958b759
@@ -70,6 +70,7 @@
|
||||
ErrorControl="ignore"
|
||||
Interactive="no">
|
||||
<ServiceConfig DelayedAutoStart="no" OnInstall="yes" OnReinstall="yes" ServiceSid="unrestricted"/>
|
||||
<util:ServiceConfig FirstFailureActionType="restart" SecondFailureActionType="restart" ThirdFailureActionType="restart" ResetPeriodInDays="1" RestartServiceDelayInSeconds="10"/>
|
||||
</ServiceInstall>
|
||||
<ServiceControl Id="StartService" Start="install" Stop="both" Remove="uninstall" Name="MISS" Wait="yes" />
|
||||
</Component>
|
||||
|
||||
+27
-15
@@ -39,6 +39,7 @@ bool PCPMapPort(PSOCKADDR_STORAGE localAddr, int localAddrLen, PSOCKADDR_STORAGE
|
||||
#define POLLING_DELAY_SEC 120
|
||||
#define PORT_MAPPING_DURATION_SEC 3600
|
||||
#define UPNP_DISCOVERY_DELAY_MS 5000
|
||||
#define GAA_INITIAL_SIZE 8192
|
||||
|
||||
static struct port_entry {
|
||||
int proto;
|
||||
@@ -233,10 +234,7 @@ bool UPnPMapPort(struct UPNPUrls* urls, struct IGDdatas* data, int proto, const
|
||||
|
||||
bool GetIP4OnLinkPrefixLength(char* lanAddressString, int* prefixLength)
|
||||
{
|
||||
union {
|
||||
IP_ADAPTER_ADDRESSES addresses;
|
||||
char buffer[8192];
|
||||
};
|
||||
PIP_ADAPTER_ADDRESSES addresses;
|
||||
ULONG error;
|
||||
ULONG length;
|
||||
PIP_ADAPTER_ADDRESSES currentAdapter;
|
||||
@@ -245,22 +243,34 @@ bool GetIP4OnLinkPrefixLength(char* lanAddressString, int* prefixLength)
|
||||
|
||||
inet_pton(AF_INET, lanAddressString, &targetAddress);
|
||||
|
||||
// Get a list of all interfaces with IPv4 addresses on the system
|
||||
length = sizeof(buffer);
|
||||
error = GetAdaptersAddresses(AF_INET,
|
||||
GAA_FLAG_SKIP_ANYCAST |
|
||||
GAA_FLAG_SKIP_MULTICAST |
|
||||
GAA_FLAG_SKIP_DNS_SERVER |
|
||||
GAA_FLAG_SKIP_FRIENDLY_NAME,
|
||||
NULL,
|
||||
&addresses,
|
||||
&length);
|
||||
addresses = NULL;
|
||||
length = GAA_INITIAL_SIZE;
|
||||
do {
|
||||
free(addresses);
|
||||
addresses = (PIP_ADAPTER_ADDRESSES)malloc(length);
|
||||
if (addresses == NULL) {
|
||||
printf("malloc(%u) failed" NL, length);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get a list of all interfaces with IPv4 addresses on the system
|
||||
error = GetAdaptersAddresses(AF_INET,
|
||||
GAA_FLAG_SKIP_ANYCAST |
|
||||
GAA_FLAG_SKIP_MULTICAST |
|
||||
GAA_FLAG_SKIP_DNS_SERVER |
|
||||
GAA_FLAG_SKIP_FRIENDLY_NAME,
|
||||
NULL,
|
||||
addresses,
|
||||
&length);
|
||||
} while (error == ERROR_BUFFER_OVERFLOW);
|
||||
|
||||
if (error != ERROR_SUCCESS) {
|
||||
printf("GetAdaptersAddresses() failed: %d" NL, error);
|
||||
free(addresses);
|
||||
return false;
|
||||
}
|
||||
|
||||
currentAdapter = &addresses;
|
||||
currentAdapter = addresses;
|
||||
currentAddress = nullptr;
|
||||
while (currentAdapter != nullptr) {
|
||||
currentAddress = currentAdapter->FirstUnicastAddress;
|
||||
@@ -271,6 +281,7 @@ bool GetIP4OnLinkPrefixLength(char* lanAddressString, int* prefixLength)
|
||||
|
||||
if (RtlEqualMemory(¤tAddrV4->sin_addr, &targetAddress, sizeof(targetAddress))) {
|
||||
*prefixLength = currentAddress->OnLinkPrefixLength;
|
||||
free(addresses);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -281,6 +292,7 @@ bool GetIP4OnLinkPrefixLength(char* lanAddressString, int* prefixLength)
|
||||
}
|
||||
|
||||
printf("No adapter found with IPv4 address: %s" NL, lanAddressString);
|
||||
free(addresses);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+10
-6
@@ -68,11 +68,13 @@ int StartUdpRelay(unsigned short Port)
|
||||
SOCKADDR_IN addr;
|
||||
HANDLE thread;
|
||||
PUDP_TUPLE tuple;
|
||||
int error;
|
||||
|
||||
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (sock == INVALID_SOCKET) {
|
||||
printf("socket() failed: %d\n", WSAGetLastError());
|
||||
return WSAGetLastError();
|
||||
error = WSAGetLastError();
|
||||
printf("socket() failed: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
// Bind to the alternate port
|
||||
@@ -80,9 +82,10 @@ int StartUdpRelay(unsigned short Port)
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(Port + RELAY_PORT_OFFSET);
|
||||
if (bind(sock, (PSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR) {
|
||||
printf("bind() failed: %d\n", WSAGetLastError());
|
||||
error = WSAGetLastError();
|
||||
printf("bind() failed: %d\n", error);
|
||||
closesocket(sock);
|
||||
return WSAGetLastError();
|
||||
return error;
|
||||
}
|
||||
|
||||
tuple = (PUDP_TUPLE)malloc(sizeof(*tuple));
|
||||
@@ -95,9 +98,10 @@ int StartUdpRelay(unsigned short Port)
|
||||
|
||||
thread = CreateThread(NULL, 0, UdpRelayThreadProc, tuple, 0, NULL);
|
||||
if (thread == NULL) {
|
||||
printf("CreateThread() failed: %d\n", GetLastError());
|
||||
error = GetLastError();
|
||||
printf("CreateThread() failed: %d\n", error);
|
||||
closesocket(sock);
|
||||
return GetLastError();
|
||||
return error;
|
||||
}
|
||||
|
||||
CloseHandle(thread);
|
||||
|
||||
+58
-36
@@ -29,6 +29,8 @@
|
||||
|
||||
#define LOOPBACK_SERVER_PORT_OFFSET -10000
|
||||
|
||||
#define GAA_INITIAL_SIZE 8192
|
||||
|
||||
static struct port_entry {
|
||||
int proto;
|
||||
int port;
|
||||
@@ -864,31 +866,40 @@ bool FindLocalInterfaceIPAddress(int family, PSOCKADDR_STORAGE addr)
|
||||
|
||||
bool FindZeroTierInterfaceAddress(PSOCKADDR_STORAGE addr)
|
||||
{
|
||||
union {
|
||||
IP_ADAPTER_ADDRESSES addresses;
|
||||
char buffer[8192];
|
||||
};
|
||||
PIP_ADAPTER_ADDRESSES addresses;
|
||||
ULONG error;
|
||||
ULONG length;
|
||||
PIP_ADAPTER_ADDRESSES currentAdapter;
|
||||
PIP_ADAPTER_UNICAST_ADDRESS currentAddress;
|
||||
|
||||
// Get all IPv4 interfaces
|
||||
length = sizeof(buffer);
|
||||
error = GetAdaptersAddresses(AF_INET,
|
||||
GAA_FLAG_SKIP_ANYCAST |
|
||||
GAA_FLAG_SKIP_MULTICAST |
|
||||
GAA_FLAG_SKIP_DNS_SERVER |
|
||||
GAA_FLAG_SKIP_FRIENDLY_NAME,
|
||||
NULL,
|
||||
&addresses,
|
||||
&length);
|
||||
addresses = NULL;
|
||||
length = GAA_INITIAL_SIZE;
|
||||
do {
|
||||
free(addresses);
|
||||
addresses = (PIP_ADAPTER_ADDRESSES)malloc(length);
|
||||
if (addresses == NULL) {
|
||||
fprintf(LOG_OUT, "malloc(%u) failed\n", length);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get all IPv4 interfaces
|
||||
error = GetAdaptersAddresses(AF_INET,
|
||||
GAA_FLAG_SKIP_ANYCAST |
|
||||
GAA_FLAG_SKIP_MULTICAST |
|
||||
GAA_FLAG_SKIP_DNS_SERVER |
|
||||
GAA_FLAG_SKIP_FRIENDLY_NAME,
|
||||
NULL,
|
||||
addresses,
|
||||
&length);
|
||||
} while (error == ERROR_BUFFER_OVERFLOW);
|
||||
|
||||
if (error != ERROR_SUCCESS) {
|
||||
fprintf(LOG_OUT, "GetAdaptersAddresses() failed: %d\n", error);
|
||||
free(addresses);
|
||||
return false;
|
||||
}
|
||||
|
||||
currentAdapter = &addresses;
|
||||
currentAdapter = addresses;
|
||||
while (currentAdapter != NULL) {
|
||||
// Look for ones that correspond to a ZeroTier device
|
||||
if (wcsstr(currentAdapter->Description, L"ZeroTier")) {
|
||||
@@ -897,6 +908,7 @@ bool FindZeroTierInterfaceAddress(PSOCKADDR_STORAGE addr)
|
||||
while (currentAddress != NULL) {
|
||||
if (currentAddress->Address.lpSockaddr->sa_family == AF_INET) {
|
||||
RtlCopyMemory(addr, currentAddress->Address.lpSockaddr, currentAddress->Address.iSockaddrLength);
|
||||
free(addresses);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -907,15 +919,13 @@ bool FindZeroTierInterfaceAddress(PSOCKADDR_STORAGE addr)
|
||||
currentAdapter = currentAdapter->Next;
|
||||
}
|
||||
|
||||
free(addresses);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FindDuplicateDefaultInterfaces(void)
|
||||
{
|
||||
union {
|
||||
IP_ADAPTER_ADDRESSES addresses;
|
||||
char buffer[8192];
|
||||
};
|
||||
PIP_ADAPTER_ADDRESSES addresses;
|
||||
ULONG error;
|
||||
ULONG length;
|
||||
MIB_IPFORWARDROW defaultRoute;
|
||||
@@ -928,24 +938,36 @@ bool FindDuplicateDefaultInterfaces(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get all IPv4 interfaces
|
||||
length = sizeof(buffer);
|
||||
error = GetAdaptersAddresses(AF_INET,
|
||||
GAA_FLAG_SKIP_UNICAST |
|
||||
GAA_FLAG_SKIP_ANYCAST |
|
||||
GAA_FLAG_SKIP_MULTICAST |
|
||||
GAA_FLAG_SKIP_DNS_SERVER |
|
||||
GAA_FLAG_INCLUDE_GATEWAYS |
|
||||
GAA_FLAG_SKIP_FRIENDLY_NAME,
|
||||
NULL,
|
||||
&addresses,
|
||||
&length);
|
||||
addresses = NULL;
|
||||
length = GAA_INITIAL_SIZE;
|
||||
do {
|
||||
free(addresses);
|
||||
addresses = (PIP_ADAPTER_ADDRESSES)malloc(length);
|
||||
if (addresses == NULL) {
|
||||
fprintf(LOG_OUT, "malloc(%u) failed\n", length);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get all IPv4 interfaces
|
||||
error = GetAdaptersAddresses(AF_INET,
|
||||
GAA_FLAG_SKIP_UNICAST |
|
||||
GAA_FLAG_SKIP_ANYCAST |
|
||||
GAA_FLAG_SKIP_MULTICAST |
|
||||
GAA_FLAG_SKIP_DNS_SERVER |
|
||||
GAA_FLAG_INCLUDE_GATEWAYS |
|
||||
GAA_FLAG_SKIP_FRIENDLY_NAME,
|
||||
NULL,
|
||||
addresses,
|
||||
&length);
|
||||
} while (error == ERROR_BUFFER_OVERFLOW);
|
||||
|
||||
if (error != ERROR_SUCCESS) {
|
||||
fprintf(LOG_OUT, "GetAdaptersAddresses() failed: %d\n", error);
|
||||
free(addresses);
|
||||
return false;
|
||||
}
|
||||
|
||||
currentAdapter = &addresses;
|
||||
currentAdapter = addresses;
|
||||
while (currentAdapter != NULL) {
|
||||
if (currentAdapter->OperStatus == IfOperStatusUp &&
|
||||
currentAdapter->FirstGatewayAddress != NULL &&
|
||||
@@ -958,6 +980,7 @@ bool FindDuplicateDefaultInterfaces(void)
|
||||
currentAdapter = currentAdapter->Next;
|
||||
}
|
||||
|
||||
free(addresses);
|
||||
return matchingInterfaces > 1;
|
||||
}
|
||||
|
||||
@@ -1490,10 +1513,9 @@ int main(int argc, char* argv[])
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Tested against a working server and it failed
|
||||
break;
|
||||
}
|
||||
|
||||
// Tested against a IPv6 working server
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+56
-40
@@ -45,15 +45,20 @@ bool getExternalAddressPortIP4(unsigned short localPort, PSOCKADDR_IN wanAddr)
|
||||
int i;
|
||||
int bytesRead;
|
||||
int err;
|
||||
bool ret;
|
||||
PSTUN_ATTRIBUTE_HEADER attribute;
|
||||
PSTUN_MAPPED_IPV4_ADDRESS_ATTRIBUTE ipv4Attrib;
|
||||
struct addrinfo* result;
|
||||
struct addrinfo hints;
|
||||
struct sockaddr_in bindAddr;
|
||||
union {
|
||||
STUN_MESSAGE hdr;
|
||||
char buf[1024];
|
||||
} resp;
|
||||
|
||||
sock = INVALID_SOCKET;
|
||||
ret = false;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_flags = AI_ADDRCONFIG;
|
||||
@@ -68,18 +73,15 @@ bool getExternalAddressPortIP4(unsigned short localPort, PSOCKADDR_IN wanAddr)
|
||||
sock = socket(hints.ai_family, hints.ai_socktype, hints.ai_protocol);
|
||||
if (sock == INVALID_SOCKET) {
|
||||
fprintf(LOG_OUT, "socket() failed: %d\n", WSAGetLastError());
|
||||
freeaddrinfo(result);
|
||||
return false;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
struct sockaddr_in bindAddr = {};
|
||||
bindAddr = {};
|
||||
bindAddr.sin_family = hints.ai_family;
|
||||
bindAddr.sin_port = htons(localPort);
|
||||
if (bind(sock, (struct sockaddr*)&bindAddr, sizeof(bindAddr)) == SOCKET_ERROR) {
|
||||
fprintf(LOG_OUT, "bind() failed: %d\n", WSAGetLastError());
|
||||
closesocket(sock);
|
||||
freeaddrinfo(result);
|
||||
return false;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
reqMsg.messageType = htons(STUN_MESSAGE_BINDING_REQUEST);
|
||||
@@ -98,57 +100,60 @@ bool getExternalAddressPortIP4(unsigned short localPort, PSOCKADDR_IN wanAddr)
|
||||
}
|
||||
}
|
||||
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(sock, &fds);
|
||||
for (;;) {
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(sock, &fds);
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
int selectRes = select(0, &fds, nullptr, nullptr, &tv);
|
||||
if (selectRes == 0) {
|
||||
// Timeout - continue looping
|
||||
continue;
|
||||
int selectRes = select(0, &fds, nullptr, nullptr, &tv);
|
||||
if (selectRes == 0) {
|
||||
// Timeout - break to the enclosing loop
|
||||
break;
|
||||
}
|
||||
else if (selectRes == SOCKET_ERROR) {
|
||||
fprintf(LOG_OUT, "select() failed: %d\n", WSAGetLastError());
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
// recvfrom() will return WSAECONNRESET if the socket has received an ICMP Port Unreachable
|
||||
// message from one of the IP addresses we've attempted communication with. The socket is still
|
||||
// operable (and may even contain queued messages to receive). We should ignore that error and
|
||||
// continue reading, otherwise exit the loop.
|
||||
bytesRead = recvfrom(sock, resp.buf, sizeof(resp.buf), 0, NULL, NULL);
|
||||
if (bytesRead != SOCKET_ERROR || WSAGetLastError() != WSAECONNRESET) {
|
||||
goto RecvDone;
|
||||
}
|
||||
}
|
||||
else if (selectRes == SOCKET_ERROR) {
|
||||
fprintf(LOG_OUT, "select() failed: %d\n", WSAGetLastError());
|
||||
closesocket(sock);
|
||||
freeaddrinfo(result);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Error handling is below
|
||||
bytesRead = recvfrom(sock, resp.buf, sizeof(resp.buf), 0, NULL, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
freeaddrinfo(result);
|
||||
closesocket(sock);
|
||||
|
||||
RecvDone:
|
||||
if (bytesRead == 0) {
|
||||
fprintf(LOG_OUT, "No response from STUN server\n");
|
||||
return false;
|
||||
goto Exit;
|
||||
}
|
||||
else if (bytesRead == SOCKET_ERROR) {
|
||||
fprintf(LOG_OUT, "Failed to read STUN binding response: %d\n", WSAGetLastError());
|
||||
return false;
|
||||
goto Exit;
|
||||
}
|
||||
else if (bytesRead < sizeof(resp.hdr)) {
|
||||
fprintf(LOG_OUT, "STUN message truncated: %d\n", bytesRead);
|
||||
return false;
|
||||
goto Exit;
|
||||
}
|
||||
else if (htonl(resp.hdr.magicCookie) != STUN_MESSAGE_COOKIE) {
|
||||
fprintf(LOG_OUT, "Bad STUN cookie value: %x\n", htonl(resp.hdr.magicCookie));
|
||||
return false;
|
||||
goto Exit;
|
||||
}
|
||||
else if (memcmp(reqMsg.transactionId, resp.hdr.transactionId, sizeof(reqMsg.transactionId))) {
|
||||
fprintf(LOG_OUT, "STUN transaction ID mismatch\n");
|
||||
return false;
|
||||
goto Exit;
|
||||
}
|
||||
else if (htons(resp.hdr.messageType) != STUN_MESSAGE_BINDING_SUCCESS) {
|
||||
fprintf(LOG_OUT, "STUN message type mismatch: %x\n", htons(resp.hdr.messageType));
|
||||
return false;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
attribute = (PSTUN_ATTRIBUTE_HEADER)(&resp.hdr + 1);
|
||||
@@ -156,7 +161,7 @@ bool getExternalAddressPortIP4(unsigned short localPort, PSOCKADDR_IN wanAddr)
|
||||
while (bytesRead > sizeof(*attribute)) {
|
||||
if (bytesRead < sizeof(*attribute) + htons(attribute->length)) {
|
||||
fprintf(LOG_OUT, "STUN attribute out of bounds: %d\n", htons(attribute->length));
|
||||
return false;
|
||||
goto Exit;
|
||||
}
|
||||
// Mask off the comprehension bit
|
||||
else if ((htons(attribute->type) & 0x7FFF) != STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS) {
|
||||
@@ -169,11 +174,11 @@ bool getExternalAddressPortIP4(unsigned short localPort, PSOCKADDR_IN wanAddr)
|
||||
ipv4Attrib = (PSTUN_MAPPED_IPV4_ADDRESS_ATTRIBUTE)attribute;
|
||||
if (htons(ipv4Attrib->hdr.length) != 8) {
|
||||
fprintf(LOG_OUT, "STUN address length mismatch: %d\n", htons(ipv4Attrib->hdr.length));
|
||||
return false;
|
||||
goto Exit;
|
||||
}
|
||||
else if (ipv4Attrib->addressFamily != 1) {
|
||||
fprintf(LOG_OUT, "STUN address family mismatch: %x\n", ipv4Attrib->addressFamily);
|
||||
return false;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
*wanAddr = {};
|
||||
@@ -183,9 +188,20 @@ bool getExternalAddressPortIP4(unsigned short localPort, PSOCKADDR_IN wanAddr)
|
||||
wanAddr->sin_port = ipv4Attrib->port ^ (short)resp.hdr.magicCookie;
|
||||
wanAddr->sin_addr.S_un.S_addr = ipv4Attrib->address ^ resp.hdr.magicCookie;
|
||||
|
||||
return true;
|
||||
ret = true;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
fprintf(LOG_OUT, "No XOR mapped address found in STUN response!\n");
|
||||
return false;
|
||||
|
||||
Exit:
|
||||
if (sock != INVALID_SOCKET) {
|
||||
closesocket(sock);
|
||||
}
|
||||
|
||||
if (result != NULL) {
|
||||
freeaddrinfo(result);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#define VER_VERSION 5,3,0,0
|
||||
#define VER_VERSION_STR "5.3.0.0"
|
||||
#define VER_VERSION 5,4,0,0
|
||||
#define VER_VERSION_STR "5.4.0.0"
|
||||
|
||||
#define VER_COMPANYNAME_STR "Moonlight Game Streaming Project"
|
||||
#define VER_PRODUCTNAME_STR "Moonlight Internet Hosting Tool"
|
||||
|
||||
Reference in New Issue
Block a user