diff options
Diffstat (limited to 'wsk.h')
-rw-r--r-- | wsk.h | 456 |
1 files changed, 456 insertions, 0 deletions
@@ -0,0 +1,456 @@ +#ifndef WSK_H +#define WSK_H 1 + +#if !defined(__MINGW64__) +#error "This was designed to work **only** with Mingw-w64! For MSVC, please check https://github.com/wbenny/KSOCKET out" +#endif + +#if (NTDDI_VERSION < NTDDI_WIN10) +#error \ + "Your mingw-w64 toolchain is too old. Please use the one provided by https://github.com/utoni/mingw-w64-ddk-template" +#endif + +#if !defined(__BYTE_ORDER__) || __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ +#error "This project requires a little endian system. Does Windows support any other?" +#endif + +// --------------------------------------------------------------- +// defines +// --------------------------------------------------------------- + +#define WSKAPI NTAPI +#define MAKE_WSK_VERSION(Mj, Mn) ((USHORT)((Mj) << 8) | (USHORT)((Mn)&0xff)) +#define WSK_NO_WAIT 0 +#define WSK_INFINITE_WAIT 0xffffffff + +#define WSK_FLAG_BASIC_SOCKET 0x00000000 +#define WSK_FLAG_LISTEN_SOCKET 0x00000001 +#define WSK_FLAG_CONNECTION_SOCKET 0x00000002 +#define WSK_FLAG_DATAGRAM_SOCKET 0x00000004 +#define WSK_FLAG_STREAM_SOCKET 0x00000008 + +#define INADDR_ANY ((ULONG)0x00000000) + +// --------------------------------------------------------------- +// forward decls / opaque structs +// --------------------------------------------------------------- + +struct _WSK_CLIENT_CONNECTION_DISPATCH; +typedef struct _WSK_CLIENT_CONNECTION_DISPATCH WSK_CLIENT_CONNECTION_DISPATCH; +typedef WSK_CLIENT_CONNECTION_DISPATCH *PWSK_CLIENT_CONNECTION_DISPATCH; +struct _WSK_CLIENT_NPI; +typedef struct _WSK_CLIENT_NPI WSK_CLIENT_NPI; +typedef struct _WSK_CLIENT_NPI *PWSK_CLIENT_NPI; +struct _WSK_PROVIDER_NPI; +typedef struct _WSK_PROVIDER_NPI WSK_PROVIDER_NPI; +typedef struct _WSK_PROVIDER_NPI *PWSK_PROVIDER_NPI; + +typedef PVOID PWSK_CLIENT; + +// --------------------------------------------------------------- +// enums +// --------------------------------------------------------------- + +typedef enum { + WskSetOption, // set socket option + WskGetOption, // get socket option + WskIoctl, // socket IOCTL + WskControlMax +} WSK_CONTROL_SOCKET_TYPE, + *PWSK_CONTROL_SOCKET_TYPE; + +enum { + AI_PASSIVE = 0x01, + AI_CANONNAME = 0x02, + AI_NUMERICHOST = 0x04, + AI_ALL = 0x0100, + AI_ADDRCONFIG = 0x0400, + AI_V4MAPPED = 0x0800, + AI_NON_AUTHORITATIVE = 0x4000, + AI_SECURE = 0x08000, + AI_RETURN_PREFERRED_NAMES = 0x10000, + AI_FQDN = 0x00020000, + AI_FILESERVER = 0x00040000 +}; + +typedef enum ADDRESS_FAMILY { + AF_UNSPEC = 0, + AF_INET = 2, + AF_INET6 = 23 +} ADDRESS_FAMILY; + +enum { + IPPROTO_ICMP = 1, + IPPROTO_IGMP = 2, + BTHPROTO_RFCOMM = 3, + IPPROTO_TCP = 6, + IPPROTO_UDP = 17, + IPPROTO_ICMPV6 = 58, + IPPROTO_RM = 113 +}; + +enum { + SOCK_STREAM = 1, + SOCK_DGRAM = 2, + SOCK_RAW = 3, + SOCK_RDM = 4, + SOCK_SEQPACKET = 5, +}; + +typedef enum { + WskInspectReject, // reject the connection request + WskInspectAccept, // proceed with accept + WskInspectPend, // delay the decision (use WskInspectComplete later) + WskInspectMax +} WSK_INSPECT_ACTION, + *PWSK_INSPECT_ACTION; + +// --------------------------------------------------------------- +// general structs +// --------------------------------------------------------------- + +typedef struct addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + char *ai_canonname; + struct sockaddr *ai_addr; + struct addrinfo *ai_next; +} ADDRINFOA, *PADDRINFOA; + +typedef struct addrinfoexA { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + char *ai_canonname; + struct sockaddr *ai_addr; + void *ai_blob; + size_t ai_bloblen; + LPGUID ai_provider; + struct addrinfoexA *ai_next; +} ADDRINFOEXA, *PADDRINFOEXA, *LPADDRINFOEXA; + +typedef struct addrinfoW { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + PWSTR ai_canonname; + struct sockaddr *ai_addr; + struct addrinfoW *ai_next; +} ADDRINFOW, *PADDRINFOW; + +typedef struct addrinfoexW { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + PWSTR ai_canonname; + struct sockaddr *ai_addr; + void *ai_blob; + size_t ai_bloblen; + LPGUID ai_provider; + struct addrinfoexW *ai_next; +} ADDRINFOEXW, *PADDRINFOEXW, *LPADDRINFOEXW; + +typedef struct sockaddr { + ADDRESS_FAMILY sa_family; + CHAR sa_data[14]; +} SOCKADDR, *PSOCKADDR, *LPSOCKADDR; + +struct in_addr { + union { + struct { + UCHAR s_b1; + UCHAR s_b2; + UCHAR s_b3; + UCHAR s_b4; + } s_un_b; + struct { + USHORT s_w1; + USHORT s_w2; + } s_un_w; + ULONG s_addr; + }; +}; + +typedef struct sockaddr_in { + short sin_family; + USHORT sin_port; + struct in_addr sin_addr; + char sin_zero[8]; +} SOCKADDR_IN, *PSOCKADDR_IN, *LPSOCKADDR_IN; + +typedef struct _WSK_SOCKET { + const VOID *Dispatch; +} WSK_SOCKET, *PWSK_SOCKET; + +typedef struct _WSK_BUF { + PMDL Mdl; // Locked MDL chain + ULONG Offset; // Offset into the "first" Mdl in the chain + SIZE_T Length; // Length of data starting from Offset +} WSK_BUF, *PWSK_BUF; + +typedef struct _WSK_BUF_LIST { + struct _WSK_BUF_LIST *Next; + WSK_BUF Buffer; +} WSK_BUF_LIST, *PWSK_BUF_LIST; + +typedef struct _WSK_DATA_INDICATION { + struct _WSK_DATA_INDICATION *Next; + WSK_BUF Buffer; +} WSK_DATA_INDICATION, *PWSK_DATA_INDICATION; + +typedef struct _WSK_INSPECT_ID { + ULONG_PTR Key; + ULONG SerialNumber; +} WSK_INSPECT_ID, *PWSK_INSPECT_ID; + +typedef struct _WSACMSGHDR { + SIZE_T cmsg_len; + INT cmsg_level; + INT cmsg_type; +} WSACMSGHDR, *PWSACMSGHDR, *LPWSACMSGHDR, CMSGHDR, *PCMSGHDR; + +typedef struct _WSK_DATAGRAM_INDICATION { + struct _WSK_DATAGRAM_INDICATION *Next; + WSK_BUF Buffer; + _Field_size_bytes_(ControlInfoLength) PCMSGHDR ControlInfo; + ULONG ControlInfoLength; + PSOCKADDR RemoteAddress; +} WSK_DATAGRAM_INDICATION, *PWSK_DATAGRAM_INDICATION; + +typedef struct _WSK_REGISTRATION { + ULONGLONG ReservedRegistrationState; + PVOID ReservedRegistrationContext; + KSPIN_LOCK ReservedRegistrationLock; +} WSK_REGISTRATION, *PWSK_REGISTRATION; + +// --------------------------------------------------------------- +// callback functions +// --------------------------------------------------------------- + +typedef NTSTATUS(WSKAPI *PFN_WSK_CONTROL_SOCKET)( + _In_ PWSK_SOCKET Socket, _In_ WSK_CONTROL_SOCKET_TYPE RequestType, + _In_ ULONG ControlCode, _In_ ULONG Level, _In_ SIZE_T InputSize, + _In_opt_ PVOID InputBuffer, _In_ SIZE_T OutputSize, + _Out_opt_ PVOID OutputBuffer, _Out_opt_ SIZE_T *OutputSizeReturned, + _In_ _Out_ PIRP Irp); +typedef NTSTATUS(WSKAPI *PFN_WSK_CLOSE_SOCKET)(_In_ PWSK_SOCKET Socket, + _Inout_ PIRP Irp); + +typedef NTSTATUS(WSKAPI *PFN_WSK_CONNECT)(_In_ PWSK_SOCKET Socket, + _In_ PSOCKADDR RemoteAddress, + ULONG Flags, _In_ _Out_ PIRP Irp); +typedef NTSTATUS(WSKAPI *PFN_WSK_BIND)(_In_ PWSK_SOCKET Socket, + _In_ PSOCKADDR LocalAddress, + _Reserved_ ULONG Flags, + _Inout_ PIRP Irp); +typedef NTSTATUS(WSKAPI *PFN_WSK_GET_LOCAL_ADDRESS)( + _In_ PWSK_SOCKET Socket, _Out_ PSOCKADDR LocalAddress, _Inout_ PIRP Irp); +typedef NTSTATUS(WSKAPI *PFN_WSK_GET_REMOTE_ADDRESS)( + _In_ PWSK_SOCKET Socket, _Out_ PSOCKADDR RemoteAddress, _Inout_ PIRP Irp); +typedef NTSTATUS(WSKAPI *PFN_WSK_SEND)(_In_ PWSK_SOCKET Socket, + _In_ PWSK_BUF Buffer, _In_ ULONG Flags, + _Inout_ PIRP Irp); +typedef NTSTATUS(WSKAPI *PFN_WSK_RECEIVE)(_In_ PWSK_SOCKET Socket, + _In_ PWSK_BUF Buffer, + _In_ ULONG Flags, _Inout_ PIRP Irp); +typedef NTSTATUS(WSKAPI *PFN_WSK_DISCONNECT)(_In_ PWSK_SOCKET Socket, + _In_opt_ PWSK_BUF Buffer, + _In_ ULONG Flags, + _Inout_ PIRP Irp); +typedef NTSTATUS(WSKAPI *PFN_WSK_RELEASE_DATA_INDICATION_LIST)( + _In_ PWSK_SOCKET Socket, _In_ PWSK_DATA_INDICATION DataIndication); +typedef NTSTATUS(WSKAPI *PFN_WSK_CONNECT_EX)(_In_ PWSK_SOCKET Socket, + _In_ PSOCKADDR RemoteAddress, + _In_opt_ PWSK_BUF Buffer, + _Reserved_ ULONG Flags, + _Inout_ PIRP Irp); +typedef NTSTATUS(WSKAPI *PFN_WSK_CONNECT_EX)(_In_ PWSK_SOCKET Socket, + _In_ PSOCKADDR RemoteAddress, + _In_opt_ PWSK_BUF Buffer, + _Reserved_ ULONG Flags, + _Inout_ PIRP Irp); +typedef void *PFN_WSK_SEND_EX; // reserved for system use +typedef void *PFN_WSK_RECEIVE_EX; // reserved for system use +typedef _At_(Irp->IoStatus.Information, __drv_allocatesMem(Mem)) + NTSTATUS(WSKAPI *PFN_WSK_ACCEPT)( + _In_ PWSK_SOCKET ListenSocket, _Reserved_ ULONG Flags, + _In_opt_ PVOID AcceptSocketContext, + _In_opt_ CONST WSK_CLIENT_CONNECTION_DISPATCH *AcceptSocketDispatch, + _Out_opt_ PSOCKADDR LocalAddress, _Out_opt_ PSOCKADDR RemoteAddress, + _Inout_ PIRP Irp); +typedef _Must_inspect_result_ NTSTATUS(WSKAPI *PFN_WSK_RECEIVE_EVENT)( + _In_opt_ PVOID SocketContext, _In_ ULONG Flags, + _In_opt_ PWSK_DATA_INDICATION DataIndication, _In_ SIZE_T BytesIndicated, + _Inout_ SIZE_T *BytesAccepted); +typedef NTSTATUS(WSKAPI *PFN_WSK_DISCONNECT_EVENT)(_In_opt_ PVOID SocketContext, + _In_ ULONG Flags); +typedef NTSTATUS(WSKAPI *PFN_WSK_SEND_BACKLOG_EVENT)( + _In_opt_ PVOID SocketContext, _In_ SIZE_T IdealBacklogSize); +typedef NTSTATUS(WSKAPI *PFN_WSK_INSPECT_COMPLETE)( + _In_ PWSK_SOCKET ListenSocket, _In_ PWSK_INSPECT_ID InspectID, + _In_ WSK_INSPECT_ACTION Action, _Inout_ PIRP Irp); +typedef NTSTATUS(WSKAPI *PFN_WSK_SEND_TO)( + _In_ PWSK_SOCKET Socket, _In_ PWSK_BUF Buffer, _Reserved_ ULONG Flags, + _In_opt_ PSOCKADDR RemoteAddress, _In_ ULONG ControlInfoLength, + _In_reads_bytes_opt_(ControlInfoLength) PCMSGHDR ControlInfo, + _Inout_ PIRP Irp); +typedef _Must_inspect_result_ NTSTATUS(WSKAPI *PFN_WSK_RECEIVE_FROM_EVENT)( + _In_opt_ PVOID SocketContext, _In_ ULONG Flags, + _In_opt_ PWSK_DATAGRAM_INDICATION DataIndication); +typedef NTSTATUS(WSKAPI *PFN_WSK_RECEIVE_FROM)( + _In_ PWSK_SOCKET Socket, _In_ PWSK_BUF Buffer, _Reserved_ ULONG Flags, + _Out_opt_ PSOCKADDR RemoteAddress, _Inout_ PULONG ControlLength, + _Out_writes_bytes_opt_(*ControlLength) PCMSGHDR ControlInfo, + _Out_opt_ PULONG ControlFlags, _Inout_ PIRP Irp); +typedef NTSTATUS(WSKAPI *PFN_WSK_RELEASE_DATAGRAM_INDICATION_LIST)( + _In_ PWSK_SOCKET Socket, _In_ PWSK_DATAGRAM_INDICATION DatagramIndication); +typedef NTSTATUS(WSKAPI *PFN_WSK_SEND_MESSAGES)( + _In_ PWSK_SOCKET Socket, _In_ PWSK_BUF_LIST BufferList, + _Reserved_ ULONG Flags, _In_opt_ PSOCKADDR RemoteAddress, + _In_ ULONG ControlInfoLength, + _In_reads_bytes_opt_(ControlInfoLength) PCMSGHDR ControlInfo, + _Inout_ PIRP Irp); +typedef _At_((void *)Irp->IoStatus.Information, __drv_allocatesMem(Mem)) + NTSTATUS(WSKAPI *PFN_WSK_SOCKET)( + _In_ PWSK_CLIENT Client, _In_ ADDRESS_FAMILY AddressFamily, + _In_ USHORT SocketType, _In_ ULONG Protocol, _In_ ULONG Flags, + _In_opt_ PVOID SocketContext, _In_opt_ CONST VOID *Dispatch, + _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, + _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor, _Inout_ PIRP Irp); +typedef _At_(Irp->IoStatus.Information, __drv_allocatesMem(Mem)) + NTSTATUS(WSKAPI *PFN_WSK_SOCKET_CONNECT)( + _In_ PWSK_CLIENT Client, _In_ USHORT SocketType, _In_ ULONG Protocol, + _In_ PSOCKADDR LocalAddress, _In_ PSOCKADDR RemoteAddress, + _Reserved_ ULONG Flags, _In_opt_ PVOID SocketContext, + _In_opt_ CONST WSK_CLIENT_CONNECTION_DISPATCH *Dispatch, + _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, + _In_opt_ PSECURITY_DESCRIPTOR SecurityDescriptor, _Inout_ PIRP Irp); +typedef NTSTATUS(WSKAPI *PFN_WSK_CONTROL_CLIENT)( + _In_ PWSK_CLIENT Client, _In_ ULONG ControlCode, _In_ SIZE_T InputSize, + _In_reads_bytes_opt_(InputSize) PVOID InputBuffer, _In_ SIZE_T OutputSize, + _Out_writes_bytes_opt_(OutputSize) PVOID OutputBuffer, + _Out_opt_ SIZE_T *OutputSizeReturned, _Inout_opt_ PIRP Irp); +typedef _At_(*Result, __drv_allocatesMem(Mem)) + NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO)( + _In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, + _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, + _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, + _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, + _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp); +typedef _At_(AddrInfo, __drv_freesMem(Mem)) + VOID(WSKAPI *PFN_WSK_FREE_ADDRESS_INFO)(_In_ PWSK_CLIENT Client, + _In_ PADDRINFOEXW AddrInfo); +typedef NTSTATUS(WSKAPI *PFN_WSK_GET_NAME_INFO)( + _In_ PWSK_CLIENT Client, _In_ PSOCKADDR SockAddr, _In_ ULONG SockAddrLength, + _Out_opt_ PUNICODE_STRING NodeName, _Out_opt_ PUNICODE_STRING ServiceName, + _In_ ULONG Flags, _In_opt_ PEPROCESS OwningProcess, + _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp); +typedef NTSTATUS(WSKAPI *PFN_WSK_CLIENT_EVENT)( + _In_opt_ PVOID ClientContext, _In_ ULONG EventType, + _In_reads_bytes_opt_(InformationLength) PVOID Information, + _In_ SIZE_T InformationLength); +_Must_inspect_result_ NTSTATUS WskRegister( + _In_ PWSK_CLIENT_NPI WskClientNpi, _Out_ PWSK_REGISTRATION WskRegistration); +_Must_inspect_result_ NTSTATUS WskCaptureProviderNPI( + _In_ PWSK_REGISTRATION WskRegistration, _In_ ULONG WaitTimeout, + _Out_ PWSK_PROVIDER_NPI WskProviderNpi); +VOID WskReleaseProviderNPI(_In_ PWSK_REGISTRATION WskRegistration); +VOID WskDeregister(_In_ PWSK_REGISTRATION WskRegistration); + +// --------------------------------------------------------------- +// function pointer structs +// --------------------------------------------------------------- + +typedef struct _WSK_CLIENT_CONNECTION_DISPATCH { + PFN_WSK_RECEIVE_EVENT WskReceiveEvent; + PFN_WSK_DISCONNECT_EVENT WskDisconnectEvent; + PFN_WSK_SEND_BACKLOG_EVENT WskSendBacklogEvent; +} WSK_CLIENT_CONNECTION_DISPATCH, *PWSK_CLIENT_CONNECTION_DISPATCH; + +typedef struct _WSK_PROVIDER_BASIC_DISPATCH { + PFN_WSK_CONTROL_SOCKET WskControlSocket; + PFN_WSK_CLOSE_SOCKET WskCloseSocket; +} WSK_PROVIDER_BASIC_DISPATCH, *PWSK_PROVIDER_BASIC_DISPATCH; + +typedef struct _WSK_PROVIDER_CONNECTION_DISPATCH { +#ifdef __cplusplus + WSK_PROVIDER_BASIC_DISPATCH Basic; +#else + WSK_PROVIDER_BASIC_DISPATCH; +#endif + PFN_WSK_BIND WskBind; + PFN_WSK_CONNECT WskConnect; + PFN_WSK_GET_LOCAL_ADDRESS WskGetLocalAddress; + PFN_WSK_GET_REMOTE_ADDRESS WskGetRemoteAddress; + PFN_WSK_SEND WskSend; + PFN_WSK_RECEIVE WskReceive; + PFN_WSK_DISCONNECT WskDisconnect; + PFN_WSK_RELEASE_DATA_INDICATION_LIST WskRelease; + PFN_WSK_CONNECT_EX WskConnectEx; + PFN_WSK_SEND_EX WskSendEx; + PFN_WSK_RECEIVE_EX WskReceiveEx; +} WSK_PROVIDER_CONNECTION_DISPATCH, *PWSK_PROVIDER_CONNECTION_DISPATCH; + +typedef struct _WSK_PROVIDER_LISTEN_DISPATCH { +#ifdef __cplusplus + WSK_PROVIDER_BASIC_DISPATCH Basic; +#else + WSK_PROVIDER_BASIC_DISPATCH; +#endif + PFN_WSK_BIND WskBind; + PFN_WSK_ACCEPT WskAccept; + PFN_WSK_INSPECT_COMPLETE WskInspectComplete; + PFN_WSK_GET_LOCAL_ADDRESS WskGetLocalAddress; +} WSK_PROVIDER_LISTEN_DISPATCH, *PWSK_PROVIDER_LISTEN_DISPATCH; + +typedef struct _WSK_PROVIDER_DATAGRAM_DISPATCH { +#ifdef __cplusplus + WSK_PROVIDER_BASIC_DISPATCH Basic; +#else + WSK_PROVIDER_BASIC_DISPATCH; +#endif + PFN_WSK_BIND WskBind; + PFN_WSK_SEND_TO WskSendTo; + PFN_WSK_RECEIVE_FROM WskReceiveFrom; + PFN_WSK_RELEASE_DATAGRAM_INDICATION_LIST WskRelease; + PFN_WSK_GET_LOCAL_ADDRESS WskGetLocalAddress; + PFN_WSK_SEND_MESSAGES WskSendMessages; +} WSK_PROVIDER_DATAGRAM_DISPATCH, *PWSK_PROVIDER_DATAGRAM_DISPATCH; + +typedef struct _WSK_PROVIDER_DISPATCH { + USHORT Version; + USHORT Reserved; + PFN_WSK_SOCKET WskSocket; + PFN_WSK_SOCKET_CONNECT WskSocketConnect; + PFN_WSK_CONTROL_CLIENT WskControlClient; + PFN_WSK_GET_ADDRESS_INFO WskGetAddressInfo; + PFN_WSK_FREE_ADDRESS_INFO WskFreeAddressInfo; + PFN_WSK_GET_NAME_INFO WskGetNameInfo; +} WSK_PROVIDER_DISPATCH, *PWSK_PROVIDER_DISPATCH; + +typedef struct _WSK_CLIENT_DISPATCH { + USHORT Version; + USHORT Reserved; + PFN_WSK_CLIENT_EVENT WskClientEvent; +} WSK_CLIENT_DISPATCH, *PWSK_CLIENT_DISPATCH; + +typedef struct _WSK_CLIENT_NPI { + PVOID ClientContext; + CONST WSK_CLIENT_DISPATCH *Dispatch; +} WSK_CLIENT_NPI, *PWSK_CLIENT_NPI; + +typedef struct _WSK_PROVIDER_NPI { + PWSK_CLIENT Client; + CONST WSK_PROVIDER_DISPATCH *Dispatch; +} WSK_PROVIDER_NPI, *PWSK_PROVIDER_NPI; + +#endif |