tun: remove tun_finalize()

tun_finalize() is essentially subset of socket_finalize() apart from:

 - using WSAFoo() functions instead of Foo()

 - "from" address is not returned

There is no clear official statement that one can use non-WSA
API on handles, so let's be on a safe side and use both.

Introduce sockethandle_t abstraction, which represents
socket and handle. Add SocketHandle* routines which call
proper API depends on underlying type in abstraction.

Rename socket_finalize() to sockethandle_finalize(), take
sockethandle_t and new routines into use and kick tun_finalize().

Signed-off-by: Lev Stipakov <lev@openvpn.net>
Acked-by: Selva Nair <selva.nair@gmail.com>
Message-Id: <20220117094917.178-1-lstipakov@gmail.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg23555.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
This commit is contained in:
Lev Stipakov 2022-01-17 11:49:17 +02:00 committed by Gert Doering
parent 544330fefe
commit bcf04b0b8e
5 changed files with 79 additions and 137 deletions

View file

@ -1115,7 +1115,8 @@ read_incoming_tun(struct context *c)
}
else
{
read_tun_buffered(c->c1.tuntap, &c->c2.buf);
sockethandle_t sh = { .is_handle = true, .h = c->c1.tuntap->hand };
sockethandle_finalize(sh, &c->c1.tuntap->reads, &c->c2.buf, NULL);
}
#else /* ifdef _WIN32 */
ASSERT(buf_init(&c->c2.buf, FRAME_HEADROOM(&c->c2.frame)));

View file

@ -3198,7 +3198,8 @@ link_socket_read_tcp(struct link_socket *sock,
if (!sock->stream_buf.residual_fully_formed)
{
#ifdef _WIN32
len = socket_finalize(sock->sd, &sock->reads, buf, NULL);
sockethandle_t sh = { .s = sock->sd };
len = sockethandle_finalize(sh, &sock->reads, buf, NULL);
#else
struct buffer frag;
stream_buf_get_next(&sock->stream_buf, &frag);
@ -3664,10 +3665,10 @@ socket_send_queue(struct link_socket *sock, struct buffer *buf, const struct lin
}
int
socket_finalize(SOCKET s,
struct overlapped_io *io,
struct buffer *buf,
struct link_socket_actual *from)
sockethandle_finalize(sockethandle_t sh,
struct overlapped_io *io,
struct buffer *buf,
struct link_socket_actual *from)
{
int ret = -1;
BOOL status;
@ -3675,13 +3676,7 @@ socket_finalize(SOCKET s,
switch (io->iostate)
{
case IOSTATE_QUEUED:
status = WSAGetOverlappedResult(
s,
&io->overlapped,
&io->size,
FALSE,
&io->flags
);
status = SocketHandleGetOverlappedResult(sh, io);
if (status)
{
/* successful return for a queued operation */
@ -3693,18 +3688,18 @@ socket_finalize(SOCKET s,
io->iostate = IOSTATE_INITIAL;
ASSERT(ResetEvent(io->overlapped.hEvent));
dmsg(D_WIN32_IO, "WIN32 I/O: Socket Completion success [%d]", ret);
dmsg(D_WIN32_IO, "WIN32 I/O: Completion success [%d]", ret);
}
else
{
/* error during a queued operation */
ret = -1;
if (WSAGetLastError() != WSA_IO_INCOMPLETE)
if (SocketHandleGetLastError(sh) != ERROR_IO_INCOMPLETE)
{
/* if no error (i.e. just not finished yet), then DON'T execute this code */
io->iostate = IOSTATE_INITIAL;
ASSERT(ResetEvent(io->overlapped.hEvent));
msg(D_WIN32_IO | M_ERRNO, "WIN32 I/O: Socket Completion error");
msg(D_WIN32_IO | M_ERRNO, "WIN32 I/O: Completion error");
}
}
break;
@ -3715,9 +3710,9 @@ socket_finalize(SOCKET s,
if (io->status)
{
/* error return for a non-queued operation */
WSASetLastError(io->status);
SocketHandleSetLastError(sh, io->status);
ret = -1;
msg(D_WIN32_IO | M_ERRNO, "WIN32 I/O: Socket Completion non-queued error");
msg(D_WIN32_IO | M_ERRNO, "WIN32 I/O: Completion non-queued error");
}
else
{
@ -3727,14 +3722,14 @@ socket_finalize(SOCKET s,
*buf = io->buf;
}
ret = io->size;
dmsg(D_WIN32_IO, "WIN32 I/O: Socket Completion non-queued success [%d]", ret);
dmsg(D_WIN32_IO, "WIN32 I/O: Completion non-queued success [%d]", ret);
}
break;
case IOSTATE_INITIAL: /* were we called without proper queueing? */
WSASetLastError(WSAEINVAL);
SocketHandleSetInvalError(sh);
ret = -1;
dmsg(D_WIN32_IO, "WIN32 I/O: Socket Completion BAD STATE");
dmsg(D_WIN32_IO, "WIN32 I/O: Completion BAD STATE");
break;
default:
@ -3742,7 +3737,7 @@ socket_finalize(SOCKET s,
}
/* return from address if requested */
if (from)
if (!sh.is_handle && from)
{
if (ret >= 0 && io->addr_defined)
{

View file

@ -262,11 +262,44 @@ int socket_send_queue(struct link_socket *sock,
struct buffer *buf,
const struct link_socket_actual *to);
int socket_finalize(
SOCKET s,
struct overlapped_io *io,
struct buffer *buf,
struct link_socket_actual *from);
typedef struct {
union {
SOCKET s;
HANDLE h;
};
bool is_handle;
} sockethandle_t;
int sockethandle_finalize(sockethandle_t sh,
struct overlapped_io *io,
struct buffer *buf,
struct link_socket_actual *from);
static inline BOOL
SocketHandleGetOverlappedResult(sockethandle_t sh, struct overlapped_io *io)
{
return sh.is_handle ?
GetOverlappedResult(sh.h, &io->overlapped, &io->size, FALSE) :
WSAGetOverlappedResult(sh.s, &io->overlapped, &io->size, FALSE, &io->flags);
}
static inline int
SocketHandleGetLastError(sockethandle_t sh)
{
return sh.is_handle ? (int)GetLastError() : WSAGetLastError();
}
inline static void
SocketHandleSetLastError(sockethandle_t sh, DWORD err)
{
sh.is_handle ? SetLastError(err) : WSASetLastError(err);
}
static inline void
SocketHandleSetInvalError(sockethandle_t sh)
{
sh.is_handle ? SetLastError(ERROR_INVALID_FUNCTION) : WSASetLastError(WSAEINVAL);
}
#else /* ifdef _WIN32 */
@ -1020,7 +1053,8 @@ link_socket_read_udp_win32(struct link_socket *sock,
struct buffer *buf,
struct link_socket_actual *from)
{
return socket_finalize(sock->sd, &sock->reads, buf, from);
sockethandle_t sh = { .s = sock->sd };
return sockethandle_finalize(sh, &sock->reads, buf, from);
}
#else /* ifdef _WIN32 */
@ -1078,9 +1112,10 @@ link_socket_write_win32(struct link_socket *sock,
{
int err = 0;
int status = 0;
sockethandle_t sh = { .s = sock->sd };
if (overlapped_io_active(&sock->writes))
{
status = socket_finalize(sock->sd, &sock->writes, NULL, NULL);
status = sockethandle_finalize(sh, &sock->writes, NULL, NULL);
if (status < 0)
{
err = WSAGetLastError();

View file

@ -3561,87 +3561,29 @@ tun_write_queue(struct tuntap *tt, struct buffer *buf)
}
int
tun_finalize(
HANDLE h,
struct overlapped_io *io,
struct buffer *buf)
tun_write_win32(struct tuntap *tt, struct buffer *buf)
{
int ret = -1;
BOOL status;
switch (io->iostate)
int err = 0;
int status = 0;
if (overlapped_io_active(&tt->writes))
{
case IOSTATE_QUEUED:
status = GetOverlappedResult(
h,
&io->overlapped,
&io->size,
FALSE
);
if (status)
{
/* successful return for a queued operation */
if (buf)
{
*buf = io->buf;
}
ret = io->size;
io->iostate = IOSTATE_INITIAL;
ASSERT(ResetEvent(io->overlapped.hEvent));
dmsg(D_WIN32_IO, "WIN32 I/O: TAP Completion success [%d]", ret);
}
else
{
/* error during a queued operation */
ret = -1;
if (GetLastError() != ERROR_IO_INCOMPLETE)
{
/* if no error (i.e. just not finished yet),
* then DON'T execute this code */
io->iostate = IOSTATE_INITIAL;
ASSERT(ResetEvent(io->overlapped.hEvent));
msg(D_WIN32_IO | M_ERRNO, "WIN32 I/O: TAP Completion error");
}
}
break;
case IOSTATE_IMMEDIATE_RETURN:
io->iostate = IOSTATE_INITIAL;
ASSERT(ResetEvent(io->overlapped.hEvent));
if (io->status)
{
/* error return for a non-queued operation */
SetLastError(io->status);
ret = -1;
msg(D_WIN32_IO | M_ERRNO, "WIN32 I/O: TAP Completion non-queued error");
}
else
{
/* successful return for a non-queued operation */
if (buf)
{
*buf = io->buf;
}
ret = io->size;
dmsg(D_WIN32_IO, "WIN32 I/O: TAP Completion non-queued success [%d]", ret);
}
break;
case IOSTATE_INITIAL: /* were we called without proper queueing? */
SetLastError(ERROR_INVALID_FUNCTION);
ret = -1;
dmsg(D_WIN32_IO, "WIN32 I/O: TAP Completion BAD STATE");
break;
default:
ASSERT(0);
sockethandle_t sh = { .is_handle = true, .h = tt->hand };
status = sockethandle_finalize(sh, &tt->writes, NULL, NULL);
if (status < 0)
{
err = GetLastError();
}
}
if (buf)
tun_write_queue(tt, buf);
if (status < 0)
{
buf->len = ret;
SetLastError(err);
return status;
}
else
{
return BLEN(buf);
}
return ret;
}
static const struct device_instance_id_interface *

View file

@ -437,8 +437,6 @@ int tun_read_queue(struct tuntap *tt, int maxsize);
int tun_write_queue(struct tuntap *tt, struct buffer *buf);
int tun_finalize(HANDLE h, struct overlapped_io *io, struct buffer *buf);
static inline bool
tuntap_stop(int status)
{
@ -466,36 +464,7 @@ tuntap_abort(int status)
return false;
}
static inline int
tun_write_win32(struct tuntap *tt, struct buffer *buf)
{
int err = 0;
int status = 0;
if (overlapped_io_active(&tt->writes))
{
status = tun_finalize(tt->hand, &tt->writes, NULL);
if (status < 0)
{
err = GetLastError();
}
}
tun_write_queue(tt, buf);
if (status < 0)
{
SetLastError(err);
return status;
}
else
{
return BLEN(buf);
}
}
static inline int
read_tun_buffered(struct tuntap *tt, struct buffer *buf)
{
return tun_finalize(tt->hand, &tt->reads, buf);
}
int tun_write_win32(struct tuntap *tt, struct buffer *buf);
static inline ULONG
wintun_ring_packet_align(ULONG size)