Impl create id with hostname

Previously, ids could only be created with an ip address. Now they can
be made with a hostname, which will be looked up by UDPC.

Also fix client still requesting connections even if
accept-new-connections flag is false.
This commit is contained in:
Stephen Seo 2020-04-26 18:36:49 +09:00
parent 5dcab1d590
commit 31ca4ddc44
5 changed files with 124 additions and 17 deletions

View file

@ -281,6 +281,8 @@ UDPC_ConnectionId UDPC_create_id_anyaddr(uint16_t port);
*/
UDPC_ConnectionId UDPC_create_id_easy(const char *addrString, uint16_t port);
UDPC_ConnectionId UDPC_create_id_hostname(const char *hostname, uint16_t port);
/*!
* \brief Creates an UDPC_HContext that holds state for connections
*
@ -678,6 +680,8 @@ UDPC_IPV6_ADDR_TYPE UDPC_strtoa(const char *addrStr);
UDPC_IPV6_ADDR_TYPE UDPC_strtoa_link(const char *addrStr, uint32_t *linkId_out);
UDPC_IPV6_ADDR_TYPE UDPC_a4toa6(uint32_t a4_be);
int UDPC_is_big_endian();
uint16_t UDPC_no16i(uint16_t i);
uint32_t UDPC_no32i(uint32_t i);

View file

@ -39,6 +39,12 @@
# include <sodium.h>
#endif
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
# include <ws2tcpip.h>
#elif UDPC_PLATFORM == UDPC_PLATFORM_MAC || UDPC_PLATFORM_LINUX
# include <netdb.h>
#endif
#define UDPC_MIN_HEADER_SIZE 20
#define UDPC_CON_HEADER_SIZE (UDPC_MIN_HEADER_SIZE+4)
#define UDPC_CCL_HEADER_SIZE (UDPC_MIN_HEADER_SIZE+4+crypto_sign_PUBLICKEYBYTES+12)

View file

@ -19,21 +19,8 @@
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
#include <netioapi.h>
static const UDPC_IPV6_ADDR_TYPE in6addr_any = UDPC_IPV6_ADDR_TYPE{{
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
}};
static const UDPC_IPV6_ADDR_TYPE in6addr_loopback = UDPC_IPV6_ADDR_TYPE{{
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 1
}};
typedef int socklen_t;
#elif UDPC_PLATFORM == UDPC_PLATFORM_MAC || UDPC_PLATFORM == UDPC_PLATFORM_LINUX
#include <sys/ioctl.h>
#include <net/if.h>
@ -319,6 +306,12 @@ void UDPC::Context::update_impl() {
switch(event.type) {
case UDPC_ET_REQUEST_CONNECT:
{
if(!isAcceptNewConnections.load()) {
UDPC_CHECK_LOG(this, UDPC_LoggingType::UDPC_WARNING,
"Ignoring connection request because "
"accept-new-connections flag is false");
break;
}
unsigned char *sk = nullptr;
unsigned char *pk = nullptr;
if(keysSet.load()) {
@ -1942,6 +1935,51 @@ UDPC_ConnectionId UDPC_create_id_easy(const char *addrString, uint16_t port) {
return result;
}
UDPC_ConnectionId UDPC_create_id_hostname(const char *hostname, uint16_t port) {
UDPC_ConnectionId result;
std::memset(&result, 0, sizeof(UDPC_ConnectionId));
result.port = port;
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
WORD wVersionRequested = MAKEWORD(2, 2);
WSADATA wsaData;
if(WSAStartup(wVersionRequested, &wsaData) != 0) {
fprintf(stderr, "Failed to initialize Winsock\n");
return result;
}
#elif UDPC_PLATFORM == UDPC_PLATFORM_MAC || UDPC_PLATFORM == UDPC_PLATFORM_LINUX
#endif
addrinfo hints;
std::memset(&hints, 0, sizeof(addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
addrinfo *lookupResult;
int error = getaddrinfo(hostname, nullptr, &hints, &lookupResult);
if(error == 0) {
if(lookupResult->ai_family == AF_INET) {
sockaddr_in *a4 = (sockaddr_in*)lookupResult->ai_addr;
result.addr = UDPC_a4toa6(a4->sin_addr.s_addr);
} else if(lookupResult->ai_family == AF_INET6) {
sockaddr_in6 *a6 = (sockaddr_in6*)lookupResult->ai_addr;
result.addr = a6->sin6_addr;
} else {
result.addr = in6addr_loopback;
}
freeaddrinfo(lookupResult);
} else {
result.addr = in6addr_loopback;
}
#if UDPC_PLATFORM == UDPC_PLATFORM_WINDOWS
WSACleanup();
#endif
return result;
}
UDPC_HContext UDPC_init(UDPC_ConnectionId listenId, int isClient, int isUsingLibsodium) {
UDPC::Context *ctx = new UDPC::Context(false);
ctx->flags.set(1, isClient != 0);
@ -3013,6 +3051,31 @@ UDPC_IPV6_ADDR_TYPE UDPC_strtoa_link(const char *addrStr, uint32_t *linkId_out)
return result;
}
UDPC_IPV6_ADDR_TYPE UDPC_a4toa6(uint32_t a4_be) {
if(a4_be == 0) {
return in6addr_any;
}
uint32_t a4 = ntohl(a4_be);
if(a4 == 0x7F000001) {
return in6addr_loopback;
}
UDPC_IPV6_ADDR_TYPE result;
for(unsigned int i = 0; i < 10; ++i) {
UDPC_IPV6_ADDR_SUB(result)[i] = 0;
}
UDPC_IPV6_ADDR_SUB(result)[10] = 0xFF;
UDPC_IPV6_ADDR_SUB(result)[11] = 0xFF;
for(unsigned int i = 0; i < 4; ++i) {
UDPC_IPV6_ADDR_SUB(result)[12 + i] = *((uint8_t*)&a4 + (3 - i));
}
return result;
}
int UDPC_is_big_endian() {
return UDPC::isBigEndian() ? 1 : 0;
}

View file

@ -318,3 +318,13 @@ TEST(UDPC, NetworkOrderEndianness) {
EXPECT_EQ(ll, 0x4000001010008040);
}
}
TEST(UDPC, a4toa6) {
EXPECT_EQ(UDPC_a4toa6(0), in6addr_any);
uint32_t a4 = htonl(0x7F000001);
EXPECT_EQ(UDPC_a4toa6(a4), in6addr_loopback);
UDPC_IPV6_ADDR_TYPE a6 = UDPC_strtoa("::FFFF:0102:0304");
a4 = htonl(0x01020304);
EXPECT_EQ(UDPC_a4toa6(a4), a6);
}

View file

@ -19,6 +19,7 @@ void usage() {
puts("-ll <addr> - listen addr");
puts("-lp <port> - listen port");
puts("-cl <addr> - connection addr (client only)");
puts("-clh <hostname> - connection hostname (client only)");
puts("-cp <port> - connection port (client only)");
puts("-t <tick_count>");
puts("-n - do not add payload to packets");
@ -28,6 +29,7 @@ void usage() {
puts("-ck <pubkey_file> - add pubkey to whitelist");
puts("-sk <pubkey> <seckey> - start with pub/sec key pair");
puts("-p <\"fallback\" or \"strict\"> - set auth policy");
puts("--hostname <hostname> - dont run test, just lookup hostname");
}
void sleep_seconds(unsigned int seconds) {
@ -48,6 +50,7 @@ int main(int argc, char **argv) {
const char *listenAddr = NULL;
const char *listenPort = NULL;
const char *connectionAddr = NULL;
const char *connectionHostname = NULL;
const char *connectionPort = NULL;
unsigned int tickLimit = 15;
int noPayload = 0;
@ -77,6 +80,9 @@ int main(int argc, char **argv) {
} else if(strcmp(argv[0], "-cl") == 0 && argc > 1) {
--argc; ++argv;
connectionAddr = argv[0];
} else if(strcmp(argv[0], "-clh") == 0 && argc > 1) {
--argc; ++argv;
connectionHostname = argv[0];
} else if(strcmp(argv[0], "-cp") == 0 && argc > 1) {
--argc; ++argv;
connectionPort = argv[0];
@ -137,6 +143,16 @@ int main(int argc, char **argv) {
usage();
return 1;
}
} else if(strcmp(argv[0], "--hostname") == 0 && argc > 1) {
--argc; ++argv;
UDPC_ConnectionId id = UDPC_create_id_hostname(argv[0], 9000);
UDPC_HContext ctx = UDPC_init(UDPC_create_id_easy("::1", 9000), 0, 0);
const char *str = UDPC_atostr(ctx, id.addr);
printf("Got addr \"%s\" for hostname \"%s\"\n", str, argv[0]);
UDPC_destroy(ctx);
return 0;
} else {
printf("ERROR: invalid argument \"%s\"\n", argv[0]);
usage();
@ -204,8 +220,8 @@ int main(int argc, char **argv) {
} else if(!listenPort) {
puts("ERROR: listenPort was not specified");
return 1;
} else if(isClient && !connectionAddr) {
puts("ERROR: connectionAddr was not specified");
} else if(isClient && !connectionAddr && !connectionHostname) {
puts("ERROR: connectionAddr or connectionHostname was not specified");
return 1;
} else if(isClient && !connectionPort) {
puts("ERROR: connectionPort was not specified");
@ -220,7 +236,15 @@ int main(int argc, char **argv) {
listenId = UDPC_create_id_easy(listenAddr, atoi(listenPort));
}
if(isClient) {
connectionId = UDPC_create_id_easy(connectionAddr, atoi(connectionPort));
if(connectionAddr) {
connectionId = UDPC_create_id_easy(connectionAddr, atoi(connectionPort));
} else /* if(connectionHostname) */ {
connectionId = UDPC_create_id_hostname(connectionHostname, atoi(connectionPort));
if(memcmp(&connectionId.addr, &in6addr_loopback, 16) == 0) {
puts("ERROR: Failed to resolve hostname");
return 1;
}
}
}
UDPC_HContext context = UDPC_init(listenId, isClient, isLibSodiumEnabled);
if(!context) {