Find a free port for management interface

Bind a socket and then close to identify
a free port and use it when starting openvpn.exe.

Try port = offset + config-index is first, matching
the current usage, and fallback to a dynamic port if
the former fails.

Trac: #1051
Signed-off-by: Selva Nair <selva.nair@gmail.com>
pull/510/head
Selva Nair 2 years ago
parent f22a45e349
commit 819629e2a5

@ -773,3 +773,54 @@ set_openssl_env_vars()
} }
} }
} }
/*
* Find a free port to bind and return it in addr.sin_port
*/
BOOL
find_free_tcp_port(SOCKADDR_IN *addr)
{
BOOL ret = false;
SOCKADDR_IN addr_bound;
WSADATA wsaData;
int len = sizeof(*addr);
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
return ret;
}
u_short old_port = addr->sin_port;
SOCKET sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sk == INVALID_SOCKET)
{
MsgToEventLog(EVENTLOG_ERROR_TYPE, L"%hs: socket open failed", __func__);
goto out;
}
while (bind(sk, (SOCKADDR *) addr, len))
{
if (addr->sin_port == 0)
{
MsgToEventLog(EVENTLOG_ERROR_TYPE, L"%hs: bind to dynamic port failed", __func__);
goto out;
}
addr->sin_port = 0;
}
if (getsockname(sk, (SOCKADDR *) &addr_bound, &len))
{
MsgToEventLog(EVENTLOG_ERROR_TYPE, L"%hs: getsockname failed", __func__);
goto out;
}
ret = true;
out:
if (sk != INVALID_SOCKET)
{
closesocket(sk);
}
addr->sin_port = ret ? addr_bound.sin_port : old_port;
WSACleanup();
return ret;
}

@ -89,4 +89,13 @@ void set_openssl_env_vars(void);
/* Return escaped copy of a string */ /* Return escaped copy of a string */
char *escape_string(const char *str); char *escape_string(const char *str);
/**
* Find a free port to bind to
* @param addr : Address to bind to -- if port >0 it's tried first.
* On return the port is set to the one found.
* @returns true on success, false on error. In case of error
* addr is unchanged.
*/
BOOL find_free_tcp_port(SOCKADDR_IN *addr);
#endif #endif

@ -2193,6 +2193,8 @@ StartOpenVPN(connection_t *c)
/* Create a management interface password */ /* Create a management interface password */
GetRandomPassword(c->manage.password, sizeof(c->manage.password) - 1); GetRandomPassword(c->manage.password, sizeof(c->manage.password) - 1);
find_free_tcp_port(&c->manage.skaddr);
/* Construct command line -- put log first */ /* Construct command line -- put log first */
_sntprintf_0(cmdline, _T("openvpn --log%ls \"%ls\" --config \"%ls\" " _sntprintf_0(cmdline, _T("openvpn --log%ls \"%ls\" --config \"%ls\" "
"--setenv IV_GUI_VER \"%hs\" --setenv IV_SSO openurl,crtext --service %ls 0 --auth-retry interact " "--setenv IV_GUI_VER \"%hs\" --setenv IV_SSO openurl,crtext --service %ls 0 --auth-retry interact "

Loading…
Cancel
Save