Skip to content

Commit 969439c

Browse files
[WSHTCPIP][TCPIP] Implement SO_KEEPALIVE, SIO_KEEPALIVE_VALS
1 parent 0572d36 commit 969439c

10 files changed

Lines changed: 179 additions & 7 deletions

File tree

dll/win32/wshtcpip/wshtcpip.c

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -167,12 +167,11 @@ GetTdiTypeId(
167167
switch (Level)
168168
{
169169
case SOL_SOCKET:
170-
*TdiType = INFO_TYPE_ADDRESS_OBJECT;
170+
*TdiType = INFO_TYPE_CONNECTION;
171171
switch (OptionName)
172172
{
173173
case SO_KEEPALIVE:
174-
/* FIXME: Return proper option */
175-
ASSERT(FALSE);
174+
*TdiId = TCP_SOCKET_KEEPALIVE;
176175
break;
177176
default:
178177
break;
@@ -352,6 +351,9 @@ WSHIoctl(
352351
OUT LPBOOL NeedsCompletion)
353352
{
354353
INT res;
354+
PSOCKET_CONTEXT Context = HelperDllSocketContext;
355+
PTCP_REQUEST_SET_INFORMATION_EX Info;
356+
PQUEUED_REQUEST Queued, NextQueued;
355357

356358
if (IoControlCode == SIO_GET_INTERFACE_LIST)
357359
{
@@ -362,6 +364,67 @@ WSHIoctl(
362364
NeedsCompletion);
363365
return res;
364366
}
367+
else if (IoControlCode == SIO_KEEPALIVE_VALS)
368+
{
369+
if (!InputBuffer || InputBufferLength != sizeof(struct tcp_keepalive))
370+
{
371+
return WSAEINVAL;
372+
}
373+
374+
Info = HeapAlloc(GetProcessHeap(), 0, sizeof(*Info) + InputBufferLength);
375+
if (!Info)
376+
return WSAENOBUFS;
377+
378+
Info->ID.toi_entity.tei_entity = Context->AddrFileEntityType;
379+
Info->ID.toi_entity.tei_instance = Context->AddrFileInstance;
380+
Info->ID.toi_class = INFO_CLASS_PROTOCOL;
381+
Info->ID.toi_type = INFO_TYPE_CONNECTION;
382+
Info->ID.toi_id = TCP_SOCKET_KEEPALIVEVALS;
383+
Info->BufferSize = InputBufferLength;
384+
memcpy(Info->Buffer, InputBuffer, InputBufferLength);
385+
386+
if (Context->SocketState == SocketStateCreated)
387+
{
388+
if (Context->RequestQueue)
389+
{
390+
Queued = Context->RequestQueue;
391+
while ((NextQueued = Queued->Next))
392+
{
393+
Queued = NextQueued;
394+
}
395+
396+
Queued->Next = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST));
397+
if (!Queued->Next)
398+
{
399+
HeapFree(GetProcessHeap(), 0, Info);
400+
return WSAENOBUFS;
401+
}
402+
403+
NextQueued = Queued->Next;
404+
NextQueued->Next = NULL;
405+
NextQueued->Info = Info;
406+
}
407+
else
408+
{
409+
Context->RequestQueue = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST));
410+
if (!Context->RequestQueue)
411+
{
412+
HeapFree(GetProcessHeap(), 0, Info);
413+
return WSAENOBUFS;
414+
}
415+
416+
Context->RequestQueue->Next = NULL;
417+
Context->RequestQueue->Info = Info;
418+
}
419+
420+
return 0;
421+
}
422+
423+
res = SendRequest(Info, sizeof(*Info) + Info->BufferSize, IOCTL_TCP_SET_INFORMATION_EX);
424+
425+
HeapFree(GetProcessHeap(), 0, Info);
426+
return res;
427+
}
365428

366429
UNIMPLEMENTED;
367430

@@ -690,9 +753,11 @@ WSHSetSocketInformation(
690753
return 0;
691754

692755
case SO_KEEPALIVE:
693-
/* FIXME -- We'll send this to TCPIP */
694-
DPRINT1("Set: SO_KEEPALIVE not yet supported\n");
695-
return 0;
756+
if (OptionLength < sizeof(DWORD))
757+
{
758+
return WSAEFAULT;
759+
}
760+
break;
696761

697762
default:
698763
/* Invalid option */

dll/win32/wshtcpip/wshtcpip.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <tdilib.h>
2222
#include <ws2tcpip.h>
2323
#include <rtlfuncs.h>
24+
#include <mstcpip.h>
2425

2526
#define EXPORT WINAPI
2627

@@ -59,6 +60,12 @@ WSHIoctl_GetInterfaceList(
5960
OUT LPDWORD NumberOfBytesReturned,
6061
OUT LPBOOL NeedsCompletion);
6162

63+
INT
64+
SendRequest(
65+
IN PVOID Request,
66+
IN DWORD RequestSize,
67+
IN DWORD IOCTL);
68+
6269
#endif /* __WSHTCPIP_H */
6370

6471
/* EOF */

drivers/network/tcpip/include/tcp.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,10 @@ BOOLEAN TCPRemoveIRP( PCONNECTION_ENDPOINT Connection, PIRP Irp );
188188

189189
NTSTATUS TCPSetNoDelay(PCONNECTION_ENDPOINT Connection, BOOLEAN Set);
190190

191+
NTSTATUS TCPSetKeepAlive(PCONNECTION_ENDPOINT Connection, BOOLEAN Set);
192+
193+
NTSTATUS TCPSetKeepAliveValues(PCONNECTION_ENDPOINT Connection, DWORD KeepAliveTime, DWORD KeepAliveInterval);
194+
191195
VOID
192196
TCPUpdateInterfaceLinkStatus(PIP_INTERFACE IF);
193197

drivers/network/tcpip/ip/lwip_glue/lwip_glue.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ err_t LibTCPGetPeerName(PTCP_PCB pcb, ip4_addr_t *const ipaddr, u16_t *con
114114
err_t LibTCPGetHostName(PTCP_PCB pcb, ip4_addr_t *const ipaddr, u16_t *const port);
115115
void LibTCPAccept(PTCP_PCB pcb, struct tcp_pcb *listen_pcb, void *arg);
116116
void LibTCPSetNoDelay(PTCP_PCB pcb, BOOLEAN Set);
117+
void LibTCPSetKeepAlive(PTCP_PCB pcb, BOOLEAN Set);
118+
void LibTcpSetKeepAliveValues(PTCP_PCB pcb, u32_t KeepAliveTime, u32_t KeepAliveInterval);
117119
void LibTCPGetSocketStatus(PTCP_PCB pcb, PULONG State);
118120

119121
/* IP functions */

drivers/network/tcpip/ip/lwip_glue/tcp.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,29 @@ LibTCPSetNoDelay(
875875
pcb->flags &= ~TF_NODELAY;
876876
}
877877

878+
void
879+
LibTCPSetKeepAlive(
880+
PTCP_PCB pcb,
881+
BOOLEAN Set)
882+
{
883+
if (Set)
884+
pcb->so_options |= SOF_KEEPALIVE;
885+
else
886+
pcb->so_options &= ~SOF_KEEPALIVE;
887+
}
888+
889+
void
890+
LibTcpSetKeepAliveValues(
891+
PTCP_PCB pcb,
892+
u32_t KeepAliveTime,
893+
u32_t KeepAliveInterval
894+
)
895+
{
896+
pcb->keep_idle = KeepAliveTime;
897+
pcb->keep_intvl = KeepAliveInterval;
898+
pcb->keep_cnt = 10;
899+
}
900+
878901
void
879902
LibTCPGetSocketStatus(
880903
PTCP_PCB pcb,

drivers/network/tcpip/ip/transport/tcp/tcp.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,37 @@ TCPSetNoDelay(
745745
return STATUS_SUCCESS;
746746
}
747747

748+
NTSTATUS
749+
TCPSetKeepAlive(
750+
PCONNECTION_ENDPOINT Connection,
751+
BOOLEAN Value)
752+
{
753+
if (!Connection)
754+
return STATUS_UNSUCCESSFUL;
755+
756+
if (Connection->SocketContext == NULL)
757+
return STATUS_UNSUCCESSFUL;
758+
759+
LibTCPSetKeepAlive(Connection->SocketContext, Value);
760+
return STATUS_SUCCESS;
761+
}
762+
763+
NTSTATUS
764+
TCPSetKeepAliveValues(
765+
PCONNECTION_ENDPOINT Connection,
766+
DWORD KeepAliveTime,
767+
DWORD KeepAliveInterval)
768+
{
769+
if (!Connection)
770+
return STATUS_UNSUCCESSFUL;
771+
772+
if (Connection->SocketContext == NULL)
773+
return STATUS_UNSUCCESSFUL;
774+
775+
LibTcpSetKeepAliveValues(Connection->SocketContext, KeepAliveTime, KeepAliveInterval);
776+
return STATUS_SUCCESS;
777+
}
778+
748779
NTSTATUS
749780
TCPGetSocketStatus(
750781
PCONNECTION_ENDPOINT Connection,

drivers/network/tcpip/lwip/src/include/lwip/opt.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2045,7 +2045,7 @@
20452045
* in seconds. (does not require sockets.c, and will affect tcp.c)
20462046
*/
20472047
#if !defined LWIP_TCP_KEEPALIVE || defined __DOXYGEN__
2048-
#define LWIP_TCP_KEEPALIVE 0
2048+
#define LWIP_TCP_KEEPALIVE 1
20492049
#endif
20502050

20512051
/**

drivers/network/tcpip/lwip/src/include/lwip/priv/tcp_priv.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,22 @@ err_t tcp_process_refused_data(struct tcp_pcb *pcb);
140140
#endif
141141

142142
#ifndef TCP_KEEPINTVL_DEFAULT
143+
#ifdef __REACTOS__
144+
/* According to https://learn.microsoft.com/en-us/windows/win32/winsock/sio-keepalive-vals, default keep alive interval is 1 second */
145+
#define TCP_KEEPINTVL_DEFAULT 1000UL /* Default Time between KEEPALIVE probes in milliseconds */
146+
#else
143147
#define TCP_KEEPINTVL_DEFAULT 75000UL /* Default Time between KEEPALIVE probes in milliseconds */
144148
#endif
149+
#endif
145150

146151
#ifndef TCP_KEEPCNT_DEFAULT
152+
#ifdef __REACTOS__
153+
/* According to https://learn.microsoft.com/en-us/windows/win32/winsock/sio-keepalive-vals, default probe count is 10 for vista+ */
154+
#define TCP_KEEPCNT_DEFAULT 10U /* Default Counter for KEEPALIVE probes */
155+
#else
147156
#define TCP_KEEPCNT_DEFAULT 9U /* Default Counter for KEEPALIVE probes */
148157
#endif
158+
#endif
149159

150160
#define TCP_MAXIDLE TCP_KEEPCNT_DEFAULT * TCP_KEEPINTVL_DEFAULT /* Maximum KEEPALIVE probe time */
151161

drivers/network/tcpip/tcpip/cinfo.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,21 @@
66
* PROGRAMMER: Jérôme Gardou
77
*/
88

9+
#include "ntdef.h"
910
#include "precomp.h"
1011

12+
typedef struct tcp_keepalive {
13+
ULONG onoff;
14+
ULONG keepalivetime;
15+
ULONG keepaliveinterval;
16+
} TCP_KEEPALIVE;
17+
1118
TDI_STATUS SetConnectionInfo(TDIObjectID *ID,
1219
PCONNECTION_ENDPOINT Connection,
1320
PVOID Buffer,
1421
UINT BufferSize)
1522
{
23+
NTSTATUS Status;
1624
ASSERT(ID->toi_type == INFO_TYPE_CONNECTION);
1725
switch (ID->toi_id)
1826
{
@@ -24,6 +32,26 @@ TDI_STATUS SetConnectionInfo(TDIObjectID *ID,
2432
Set = *(BOOLEAN*)Buffer;
2533
return TCPSetNoDelay(Connection, Set);
2634
}
35+
case TCP_SOCKET_KEEPALIVE:
36+
{
37+
DWORD Set;
38+
if (BufferSize < sizeof(DWORD))
39+
return TDI_INVALID_PARAMETER;
40+
Set = *(DWORD*)Buffer;
41+
return TCPSetKeepAlive(Connection, Set);
42+
}
43+
case TCP_SOCKET_KEEPALIVEVALS:
44+
{
45+
TCP_KEEPALIVE Set;
46+
if (BufferSize < sizeof(TCP_KEEPALIVE))
47+
return TDI_INVALID_PARAMETER;
48+
Set = *(TCP_KEEPALIVE*)Buffer;
49+
Status = TCPSetKeepAlive(Connection, Set.onoff);
50+
if (!NT_SUCCESS(Status))
51+
return Status;
52+
53+
return TCPSetKeepAliveValues(Connection, Set.keepalivetime, Set.keepaliveinterval);
54+
}
2755
default:
2856
DbgPrint("TCPIP: Unknown connection info ID: %u.\n", ID->toi_id);
2957
}

sdk/include/psdk/tcpioctl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@
105105

106106
/* TCP connection options */
107107
#define TCP_SOCKET_NODELAY 1
108+
#define TCP_SOCKET_KEEPALIVE 2
109+
#define TCP_SOCKET_KEEPALIVEVALS 3
108110

109111
typedef struct IFEntry
110112
{

0 commit comments

Comments
 (0)