mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2024-11-30 21:33:34 +08:00
libwinpr-winsock: implement interface listing with WSAIoctl
This commit is contained in:
parent
f9885da81c
commit
a6c292742e
@ -56,6 +56,12 @@
|
||||
#define _getprotobynumber getprotobynumber
|
||||
#define _getprotobyname getprotobyname
|
||||
|
||||
#define _IFF_UP IFF_UP
|
||||
#define _IFF_BROADCAST IFF_BROADCAST
|
||||
#define _IFF_LOOPBACK IFF_LOOPBACK
|
||||
#define _IFF_POINTTOPOINT IFF_POINTTOPOINT
|
||||
#define _IFF_MULTICAST IFF_MULTICAST
|
||||
|
||||
#if (_WIN32_WINNT < 0x0600)
|
||||
|
||||
PCSTR inet_ntop(INT Family, PVOID pAddr, PSTR pStringBuf, size_t StringBufSize);
|
||||
@ -155,6 +161,123 @@ typedef struct WSAData
|
||||
#define MAKEWORD(a,b) ((WORD)(((BYTE)((DWORD_PTR)(a) & 0xFF)) | (((WORD)((BYTE)((DWORD_PTR)(b) & 0xFF))) << 8)))
|
||||
#endif
|
||||
|
||||
typedef struct in6_addr IN6_ADDR;
|
||||
typedef struct in6_addr* PIN6_ADDR;
|
||||
typedef struct in6_addr* LPIN6_ADDR;
|
||||
|
||||
struct sockaddr_in6_old
|
||||
{
|
||||
SHORT sin6_family;
|
||||
USHORT sin6_port;
|
||||
ULONG sin6_flowinfo;
|
||||
IN6_ADDR sin6_addr;
|
||||
};
|
||||
|
||||
typedef union sockaddr_gen
|
||||
{
|
||||
struct sockaddr Address;
|
||||
struct sockaddr_in AddressIn;
|
||||
struct sockaddr_in6_old AddressIn6;
|
||||
} sockaddr_gen;
|
||||
|
||||
#define _IFF_UP 0x00000001
|
||||
#define _IFF_BROADCAST 0x00000002
|
||||
#define _IFF_LOOPBACK 0x00000004
|
||||
#define _IFF_POINTTOPOINT 0x00000008
|
||||
#define _IFF_MULTICAST 0x00000010
|
||||
|
||||
struct _INTERFACE_INFO
|
||||
{
|
||||
ULONG iiFlags;
|
||||
sockaddr_gen iiAddress;
|
||||
sockaddr_gen iiBroadcastAddress;
|
||||
sockaddr_gen iiNetmask;
|
||||
};
|
||||
typedef struct _INTERFACE_INFO INTERFACE_INFO;
|
||||
typedef INTERFACE_INFO* LPINTERFACE_INFO;
|
||||
|
||||
#define MAX_PROTOCOL_CHAIN 7
|
||||
#define WSAPROTOCOL_LEN 255
|
||||
|
||||
typedef struct _WSAPROTOCOLCHAIN
|
||||
{
|
||||
int ChainLen;
|
||||
DWORD ChainEntries[MAX_PROTOCOL_CHAIN];
|
||||
}
|
||||
WSAPROTOCOLCHAIN, *LPWSAPROTOCOLCHAIN;
|
||||
|
||||
typedef struct _WSAPROTOCOL_INFOA
|
||||
{
|
||||
DWORD dwServiceFlags1;
|
||||
DWORD dwServiceFlags2;
|
||||
DWORD dwServiceFlags3;
|
||||
DWORD dwServiceFlags4;
|
||||
DWORD dwProviderFlags;
|
||||
GUID ProviderId;
|
||||
DWORD dwCatalogEntryId;
|
||||
WSAPROTOCOLCHAIN ProtocolChain;
|
||||
int iVersion;
|
||||
int iAddressFamily;
|
||||
int iMaxSockAddr;
|
||||
int iMinSockAddr;
|
||||
int iSocketType;
|
||||
int iProtocol;
|
||||
int iProtocolMaxOffset;
|
||||
int iNetworkByteOrder;
|
||||
int iSecurityScheme;
|
||||
DWORD dwMessageSize;
|
||||
DWORD dwProviderReserved;
|
||||
CHAR szProtocol[WSAPROTOCOL_LEN+1];
|
||||
}
|
||||
WSAPROTOCOL_INFOA, *LPWSAPROTOCOL_INFOA;
|
||||
|
||||
typedef struct _WSAPROTOCOL_INFOW
|
||||
{
|
||||
DWORD dwServiceFlags1;
|
||||
DWORD dwServiceFlags2;
|
||||
DWORD dwServiceFlags3;
|
||||
DWORD dwServiceFlags4;
|
||||
DWORD dwProviderFlags;
|
||||
GUID ProviderId;
|
||||
DWORD dwCatalogEntryId;
|
||||
WSAPROTOCOLCHAIN ProtocolChain;
|
||||
int iVersion;
|
||||
int iAddressFamily;
|
||||
int iMaxSockAddr;
|
||||
int iMinSockAddr;
|
||||
int iSocketType;
|
||||
int iProtocol;
|
||||
int iProtocolMaxOffset;
|
||||
int iNetworkByteOrder;
|
||||
int iSecurityScheme;
|
||||
DWORD dwMessageSize;
|
||||
DWORD dwProviderReserved;
|
||||
WCHAR szProtocol[WSAPROTOCOL_LEN+1];
|
||||
}
|
||||
WSAPROTOCOL_INFOW, *LPWSAPROTOCOL_INFOW;
|
||||
|
||||
typedef void (CALLBACK * LPWSAOVERLAPPED_COMPLETION_ROUTINE)(DWORD dwError,
|
||||
DWORD cbTransferred, LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags);
|
||||
|
||||
typedef UINT32 GROUP;
|
||||
#define SG_UNCONSTRAINED_GROUP 0x01
|
||||
#define SG_CONSTRAINED_GROUP 0x02
|
||||
|
||||
#define SIO_GET_INTERFACE_LIST _IOR('t', 127, ULONG)
|
||||
#define SIO_GET_INTERFACE_LIST_EX _IOR('t', 126, ULONG)
|
||||
#define SIO_SET_MULTICAST_FILTER _IOW('t', 125, ULONG)
|
||||
#define SIO_GET_MULTICAST_FILTER _IOW('t', 124 | IOC_IN, ULONG)
|
||||
#define SIOCSIPMSFILTER SIO_SET_MULTICAST_FILTER
|
||||
#define SIOCGIPMSFILTER SIO_GET_MULTICAST_FILTER
|
||||
|
||||
#ifdef UNICODE
|
||||
#define WSAPROTOCOL_INFO WSAPROTOCOL_INFOW
|
||||
#define LPWSAPROTOCOL_INFO LPWSAPROTOCOL_INFOW
|
||||
#else
|
||||
#define WSAPROTOCOL_INFO WSAPROTOCOL_INFOA
|
||||
#define LPWSAPROTOCOL_INFO LPWSAPROTOCOL_INFOA
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -175,6 +298,14 @@ WINPR_API int WSAEventSelect(SOCKET s, WSAEVENT hEventObject, LONG lNetworkEvent
|
||||
WINPR_API DWORD WSAWaitForMultipleEvents(DWORD cEvents,
|
||||
const HANDLE* lphEvents, BOOL fWaitAll, DWORD dwTimeout, BOOL fAlertable);
|
||||
|
||||
WINPR_API SOCKET WSASocketA(int af, int type, int protocol, LPWSAPROTOCOL_INFOA lpProtocolInfo, GROUP g, DWORD dwFlags);
|
||||
WINPR_API SOCKET WSASocketW(int af, int type, int protocol, LPWSAPROTOCOL_INFOW lpProtocolInfo, GROUP g, DWORD dwFlags);
|
||||
|
||||
WINPR_API int WSAIoctl(SOCKET s, DWORD dwIoControlCode, LPVOID lpvInBuffer,
|
||||
DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
|
||||
LPDWORD lpcbBytesReturned, LPWSAOVERLAPPED lpOverlapped,
|
||||
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
|
||||
|
||||
WINPR_API SOCKET _accept(SOCKET s, struct sockaddr* addr, int* addrlen);
|
||||
WINPR_API int _bind(SOCKET s, const struct sockaddr* addr, int namelen);
|
||||
WINPR_API int closesocket(SOCKET s);
|
||||
@ -210,6 +341,12 @@ WINPR_API struct protoent* _getprotobyname(const char* name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UNICODE
|
||||
#define WSASocket WSASocketW
|
||||
#else
|
||||
#define WSASocket WSASocketA
|
||||
#endif
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#endif /* WINPR_WINSOCK_H */
|
||||
|
@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/thread.h>
|
||||
#include <winpr/interlocked.h>
|
||||
|
@ -650,6 +650,151 @@ DWORD WSAWaitForMultipleEvents(DWORD cEvents, const HANDLE* lphEvents, BOOL fWai
|
||||
return WaitForMultipleObjectsEx(cEvents, lphEvents, fWaitAll, dwTimeout, fAlertable);
|
||||
}
|
||||
|
||||
SOCKET WSASocketA(int af, int type, int protocol, LPWSAPROTOCOL_INFOA lpProtocolInfo, GROUP g, DWORD dwFlags)
|
||||
{
|
||||
SOCKET s;
|
||||
|
||||
s = _socket(af, type, protocol);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
SOCKET WSASocketW(int af, int type, int protocol, LPWSAPROTOCOL_INFOW lpProtocolInfo, GROUP g, DWORD dwFlags)
|
||||
{
|
||||
return WSASocketA(af, type, protocol, (LPWSAPROTOCOL_INFOA) lpProtocolInfo, g, dwFlags);
|
||||
}
|
||||
|
||||
int WSAIoctl(SOCKET s, DWORD dwIoControlCode, LPVOID lpvInBuffer,
|
||||
DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer,
|
||||
LPDWORD lpcbBytesReturned, LPWSAOVERLAPPED lpOverlapped,
|
||||
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
|
||||
{
|
||||
int fd;
|
||||
int index;
|
||||
ULONG nFlags;
|
||||
size_t offset;
|
||||
size_t ifreq_len;
|
||||
struct ifreq* ifreq;
|
||||
struct ifconf ifconf;
|
||||
char address[128];
|
||||
char broadcast[128];
|
||||
char netmask[128];
|
||||
char buffer[4096];
|
||||
int numInterfaces;
|
||||
int maxNumInterfaces;
|
||||
INTERFACE_INFO* pInterface;
|
||||
INTERFACE_INFO* pInterfaces;
|
||||
struct sockaddr_in* pAddress;
|
||||
struct sockaddr_in* pBroadcast;
|
||||
struct sockaddr_in* pNetmask;
|
||||
|
||||
if ((dwIoControlCode != SIO_GET_INTERFACE_LIST) ||
|
||||
(!lpvOutBuffer || !cbOutBuffer || !lpcbBytesReturned))
|
||||
{
|
||||
WSASetLastError(WSAEINVAL);
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
fd = (int) s;
|
||||
pInterfaces = (INTERFACE_INFO*) lpvOutBuffer;
|
||||
maxNumInterfaces = cbOutBuffer / sizeof(INTERFACE_INFO);
|
||||
|
||||
ifconf.ifc_len = sizeof(buffer);
|
||||
ifconf.ifc_buf = buffer;
|
||||
|
||||
if (ioctl(fd, SIOCGIFCONF, &ifconf) != 0)
|
||||
{
|
||||
WSASetLastError(WSAENETDOWN);
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
offset = 0;
|
||||
numInterfaces = 0;
|
||||
ifreq = ifconf.ifc_req;
|
||||
|
||||
while ((offset < ifconf.ifc_len) && (numInterfaces < maxNumInterfaces))
|
||||
{
|
||||
pInterface = &pInterfaces[index];
|
||||
pAddress = (struct sockaddr_in*) &pInterface->iiAddress;
|
||||
pBroadcast = (struct sockaddr_in*) &pInterface->iiBroadcastAddress;
|
||||
pNetmask = (struct sockaddr_in*) &pInterface->iiNetmask;
|
||||
|
||||
if (ioctl(fd, SIOCGIFFLAGS, ifreq) != 0)
|
||||
goto next_ifreq;
|
||||
|
||||
nFlags = 0;
|
||||
|
||||
if (ifreq->ifr_flags & IFF_UP)
|
||||
nFlags |= _IFF_UP;
|
||||
|
||||
if (ifreq->ifr_flags & IFF_BROADCAST)
|
||||
nFlags |= _IFF_BROADCAST;
|
||||
|
||||
if (ifreq->ifr_flags & IFF_LOOPBACK)
|
||||
nFlags |= _IFF_LOOPBACK;
|
||||
|
||||
if (ifreq->ifr_flags & IFF_POINTOPOINT)
|
||||
nFlags |= _IFF_POINTTOPOINT;
|
||||
|
||||
if (ifreq->ifr_flags & IFF_MULTICAST)
|
||||
nFlags |= _IFF_MULTICAST;
|
||||
|
||||
pInterface->iiFlags = nFlags;
|
||||
|
||||
if (ioctl(fd, SIOCGIFADDR, ifreq) != 0)
|
||||
goto next_ifreq;
|
||||
|
||||
if ((ifreq->ifr_addr.sa_family != AF_INET) && (ifreq->ifr_addr.sa_family != AF_INET6))
|
||||
goto next_ifreq;
|
||||
|
||||
getnameinfo(&ifreq->ifr_addr, sizeof(ifreq->ifr_addr),
|
||||
address, sizeof(address), 0, 0, NI_NUMERICHOST);
|
||||
|
||||
inet_pton(ifreq->ifr_addr.sa_family, address, (void*) &pAddress->sin_addr);
|
||||
|
||||
if (ioctl(fd, SIOCGIFBRDADDR, ifreq) != 0)
|
||||
goto next_ifreq;
|
||||
|
||||
if ((ifreq->ifr_addr.sa_family != AF_INET) && (ifreq->ifr_addr.sa_family != AF_INET6))
|
||||
goto next_ifreq;
|
||||
|
||||
getnameinfo(&ifreq->ifr_addr, sizeof(ifreq->ifr_addr),
|
||||
broadcast, sizeof(broadcast), 0, 0, NI_NUMERICHOST);
|
||||
|
||||
inet_pton(ifreq->ifr_addr.sa_family, broadcast, (void*) &pBroadcast->sin_addr);
|
||||
|
||||
if (ioctl(fd, SIOCGIFNETMASK, ifreq) != 0)
|
||||
goto next_ifreq;
|
||||
|
||||
if ((ifreq->ifr_addr.sa_family != AF_INET) && (ifreq->ifr_addr.sa_family != AF_INET6))
|
||||
goto next_ifreq;
|
||||
|
||||
getnameinfo(&ifreq->ifr_addr, sizeof(ifreq->ifr_addr),
|
||||
netmask, sizeof(netmask), 0, 0, NI_NUMERICHOST);
|
||||
|
||||
inet_pton(ifreq->ifr_addr.sa_family, netmask, (void*) &pNetmask->sin_addr);
|
||||
|
||||
numInterfaces++;
|
||||
|
||||
next_ifreq:
|
||||
|
||||
#ifndef __linux__
|
||||
ifreq_len = IFNAMSIZ + ifreq->ifr_addr.sa_len;
|
||||
#else
|
||||
ifreq_len = sizeof(*ifreq);
|
||||
#endif
|
||||
|
||||
ifreq = (struct ifreq*) &((BYTE*) ifreq)[ifreq_len];
|
||||
offset += ifreq_len;
|
||||
index++;
|
||||
}
|
||||
|
||||
*lpcbBytesReturned = (DWORD) (numInterfaces * sizeof(INTERFACE_INFO));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SOCKET _accept(SOCKET s, struct sockaddr* addr, int* addrlen)
|
||||
{
|
||||
int status;
|
||||
|
Loading…
Reference in New Issue
Block a user