mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-06 09:50:28 +00:00
Added initial implementation of SIOCGIFCONFIG, SIOCGIFADDR, SIOCGIFFLAGS
This commit is contained in:
parent
70828ee0ca
commit
08765c0850
3 changed files with 253 additions and 106 deletions
|
@ -23,95 +23,21 @@
|
||||||
#include "libc/sock/sock.h"
|
#include "libc/sock/sock.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
#include "libc/sysv/consts/iff.h"
|
||||||
#include "libc/nt/winsock.h"
|
#include "libc/nt/winsock.h"
|
||||||
#include "libc/nt/errors.h"
|
#include "libc/nt/errors.h"
|
||||||
|
#include "libc/nt/iphlpapi.h"
|
||||||
|
#include "libc/nt/struct/ipAdapterAddress.h"
|
||||||
|
#include "libc/nt/windows.h" /* Needed for WideCharToMultiByte */
|
||||||
|
#include "libc/bits/weaken.h"
|
||||||
|
#include "libc/assert.h"
|
||||||
|
|
||||||
// TODO: Remove me
|
// TODO: Remove me
|
||||||
#include "libc/bits/weaken.h"
|
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
#define PRINTF weaken(printf)
|
#define PRINTF weaken(printf)
|
||||||
|
|
||||||
#define MAX_INTERFACES 32
|
#define MAX_INTERFACES 32
|
||||||
|
|
||||||
#if 1
|
|
||||||
|
|
||||||
#define GAA_FLAG_SKIP_UNICAST 0x0001
|
|
||||||
#define GAA_FLAG_SKIP_ANYCAST 0x0002
|
|
||||||
#define GAA_FLAG_SKIP_MULTICAST 0x0004
|
|
||||||
#define GAA_FLAG_SKIP_DNS_SERVER 0x0008
|
|
||||||
#define GAA_FLAG_INCLUDE_PREFIX 0x0010
|
|
||||||
#define GAA_FLAG_SKIP_FRIENDLY_NAME 0x0020
|
|
||||||
#define GAA_FLAG_INCLUDE_WINS_INFO 0x0040
|
|
||||||
#define GAA_FLAG_INCLUDE_GATEWAYS 0x0080
|
|
||||||
#define GAA_FLAG_INCLUDE_ALL_INTERFACES 0x0100
|
|
||||||
#define GAA_FLAG_INCLUDE_ALL_COMPARTMENTS 0x0200
|
|
||||||
#define GAA_FLAG_INCLUDE_TUNNEL_BINDINGORDER 0x0400
|
|
||||||
#define GAA_FLAG_SKIP_DNS_INFO 0x0800
|
|
||||||
|
|
||||||
typedef struct _IP_ADAPTER_ADDRESSES_XP {
|
|
||||||
union {
|
|
||||||
uint64_t Alignment;
|
|
||||||
struct {
|
|
||||||
uint32_t Length;
|
|
||||||
uint32_t IfIndex;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
struct _IP_ADAPTER_ADDRESSES_XP *Next;
|
|
||||||
char * AdapterName;
|
|
||||||
void * FirstUnicastAddress;
|
|
||||||
void * FirstAnycastAddress;
|
|
||||||
void * FirstMulticastAddress;
|
|
||||||
void * FirstDnsServerAddress;
|
|
||||||
wchar_t *DnsSuffix;
|
|
||||||
wchar_t *Description;
|
|
||||||
wchar_t *FriendlyName;
|
|
||||||
/* Filler */
|
|
||||||
} IP_ADAPTER_ADDRESSES_XP, *PIP_ADAPTER_ADDRESSES_XP;
|
|
||||||
|
|
||||||
extern unsigned long GetAdaptersAddresses(
|
|
||||||
uint32_t Family,
|
|
||||||
uint32_t Flags,
|
|
||||||
void * Reserved,
|
|
||||||
char *AdapterAddresses,
|
|
||||||
uint32_t *SizePointer);
|
|
||||||
|
|
||||||
textwindows int ioctl_siocgifconf_nt(int fd, struct ifconf *ifc) {
|
|
||||||
uint32_t rv, size;
|
|
||||||
char * adapter_addresses;
|
|
||||||
struct _IP_ADAPTER_ADDRESSES_XP *aa;
|
|
||||||
|
|
||||||
PRINTF("FABDEBUG> ioctl(SIOCGIFCONF) for Windows... printf=%p, GetAdaptersAddresses=%p\n", weaken(printf), weaken(GetAdaptersAddresses));
|
|
||||||
if (!weaken(GetAdaptersAddresses)) {
|
|
||||||
PRINTF("FABDEBUG> NULL GetAdaptersAddresses\n");
|
|
||||||
return enomem();
|
|
||||||
}
|
|
||||||
rv = weaken(GetAdaptersAddresses)(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, NULL, &size);
|
|
||||||
if (rv != kNtErrorBufferOverflow) {
|
|
||||||
PRINTF("FABDEBUG> GetAdaptersAddresses failed %d\n", WSAGetLastError());
|
|
||||||
return ebadf();
|
|
||||||
}
|
|
||||||
PRINTF("FABDEBUG> size=%lu\n", size);
|
|
||||||
|
|
||||||
adapter_addresses = (char *)weaken(malloc)(size);
|
|
||||||
if (!adapter_addresses) {
|
|
||||||
return enomem();
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, adapter_addresses, &size);
|
|
||||||
if (rv != kNtErrorSuccess) {
|
|
||||||
PRINTF("FABDEBUG> GetAdaptersAddresses failed %d\n", WSAGetLastError());
|
|
||||||
weaken(free)(adapter_addresses);
|
|
||||||
return efault();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (aa = (struct _IP_ADAPTER_ADDRESSES_XP *)adapter_addresses; aa != NULL; aa = aa->Next) {
|
|
||||||
PRINTF("FABDEBUG> Adapter name = %s", aa->AdapterName);
|
|
||||||
}
|
|
||||||
weaken(free)(adapter_addresses);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/* Reference:
|
/* Reference:
|
||||||
* - Description of ioctls: https://docs.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls
|
* - Description of ioctls: https://docs.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls
|
||||||
* - Structure INTERFACE_INFO: https://docs.microsoft.com/en-us/windows/win32/api/ws2ipdef/ns-ws2ipdef-interface_info
|
* - Structure INTERFACE_INFO: https://docs.microsoft.com/en-us/windows/win32/api/ws2ipdef/ns-ws2ipdef-interface_info
|
||||||
|
@ -119,29 +45,250 @@ textwindows int ioctl_siocgifconf_nt(int fd, struct ifconf *ifc) {
|
||||||
* - Using SIOCGIFCONF in Win32: https://docs.microsoft.com/en-us/windows/win32/winsock/using-unix-ioctls-in-winsock
|
* - Using SIOCGIFCONF in Win32: https://docs.microsoft.com/en-us/windows/win32/winsock/using-unix-ioctls-in-winsock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
textwindows int ioctl_siocgifconf_nt(int fd, struct ifconf *ifc) {
|
|
||||||
struct NtInterfaceInfo iflist[MAX_INTERFACES];
|
|
||||||
uint32_t dwBytes;
|
|
||||||
int ret;
|
|
||||||
int i, count;
|
|
||||||
|
|
||||||
if (g_fds.p[fd].kind != kFdSocket) {
|
/* Design note:
|
||||||
return ebadf();
|
* Because the Linux struct ifreq.ifr_name has a max length of 16, this could
|
||||||
}
|
* potentially lead to ambiguouity in interfaces.
|
||||||
|
* E.g. "Ethernet Interface 1", "Ethernet Interface 2" they are both truncated
|
||||||
|
* as "Ethernet Interfa"
|
||||||
|
* Since subsequent ioctl() (e.g. SIOCGIFFLAGS) uses this name to
|
||||||
|
* identify the speficif interface, we need to make sure that all the returned
|
||||||
|
* names are unique and have a way to corelate to the original adapter addresses
|
||||||
|
* record.
|
||||||
|
*/
|
||||||
|
struct HostAdapterDesc {
|
||||||
|
char name[IFNAMSIZ]; /* Given name */
|
||||||
|
NtIpAdapterAddresses * addresses; /* NULL = invalid record */
|
||||||
|
};
|
||||||
|
|
||||||
ret = WSAIoctl(g_fds.p[fd].handle, kNtSioGetInterfaceList, NULL, 0, &iflist, sizeof(iflist), &dwBytes, NULL, NULL);
|
NtIpAdapterAddresses * theHostAdapterAddress;
|
||||||
if (ret == -1) {
|
struct HostAdapterDesc theAdapterName[MAX_INTERFACES];
|
||||||
PRINTF("FABDEBUG> WSAIoctl failed %d\n", WSAGetLastError());
|
|
||||||
return weaken(__winsockerr)();
|
|
||||||
}
|
|
||||||
|
|
||||||
PRINTF("FABDEBUG> WSAIoctl success\n");
|
|
||||||
count = dwBytes / sizeof(struct NtInterfaceInfo);
|
/* Given a short adapter name, look into theAdapterName to see if there is
|
||||||
PRINTF("CI> SIO_GET_INTERFACE_LIST success:\n");
|
* an adapter with the same name. Returns the index of theAdapterName
|
||||||
for (i = 0; i < count; ++i) {
|
* if found, or -1 if not found
|
||||||
PRINTF("CI>\t #i: addr=%08x, flags=%08x, bcast=%08x\n", i, iflist[i].iiAddress.sin_addr.s_addr, iflist[i].iiFlags, iflist[i].iiBroadcastAddress.sin_addr.s_addr);
|
*/
|
||||||
}
|
static int findAdapterByName(const char *name) {
|
||||||
return ret;
|
int i;
|
||||||
|
for (i = 0; (i < MAX_INTERFACES) && theAdapterName[i].addresses; ++i) {
|
||||||
|
if (!strncmp(name, theAdapterName[i].name, IFNAMSIZ)) {
|
||||||
|
/* Found */
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Not found */
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
static void freeAdapterInfo(void) {
|
||||||
|
if (theHostAdapterAddress) {
|
||||||
|
/* Free any existing adapter informations */
|
||||||
|
weaken(free)(theHostAdapterAddress);
|
||||||
|
theHostAdapterAddress = NULL;
|
||||||
|
memset(theAdapterName, 0, sizeof(theAdapterName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Sets theHostAdapterAddress.
|
||||||
|
* Returns -1 in case of failure (setting errno appropriately), 0 if success */
|
||||||
|
static int _readAdapterAddresses(void) {
|
||||||
|
uint32_t size, rc;
|
||||||
|
PRINTF("FABDEBUG> _readAdapterAddresses:\n");
|
||||||
|
|
||||||
|
assert(theHostAdapterAddress == NULL);
|
||||||
|
assert(weaken(GetAdaptersAddresses));
|
||||||
|
assert(weaken(WideCharToMultiByte));
|
||||||
|
|
||||||
|
/* Calculate the required data size
|
||||||
|
* Note: alternatively you can use AF_UNSPEC to also return IPv6 interfaces
|
||||||
|
*/
|
||||||
|
rc = weaken(GetAdaptersAddresses)(AF_INET,
|
||||||
|
NT_GAA_FLAG_INCLUDE_PREFIX,
|
||||||
|
NULL, /* Reserved */
|
||||||
|
NULL, /* Ptr */
|
||||||
|
&size);
|
||||||
|
if (rc != kNtErrorBufferOverflow) {
|
||||||
|
PRINTF("FABDEBUG> \tGetAdaptersAddresses failed with error %d\n", WSAGetLastError());
|
||||||
|
return ebadf();
|
||||||
|
}
|
||||||
|
PRINTF("FABDEBUG> \tsize required=%lu, allocating...\n", size);
|
||||||
|
// TODO: Do we need to access malloc/free through a weak ref?
|
||||||
|
theHostAdapterAddress = (NtIpAdapterAddresses *)weaken(malloc)(size);
|
||||||
|
if (!theHostAdapterAddress) {
|
||||||
|
PRINTF("FABDEBUG> \tmalloc failed\n");
|
||||||
|
return enomem();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Re-run GetAdaptersAddresses this time with a valid buffer */
|
||||||
|
rc = weaken(GetAdaptersAddresses)(AF_INET,
|
||||||
|
NT_GAA_FLAG_INCLUDE_PREFIX,
|
||||||
|
NULL,
|
||||||
|
theHostAdapterAddress,
|
||||||
|
&size);
|
||||||
|
if (rc != kNtErrorSuccess) {
|
||||||
|
PRINTF("FABDEBUG> GetAdaptersAddresses failed %d\n", WSAGetLastError());
|
||||||
|
freeAdapterInfo();
|
||||||
|
return efault();
|
||||||
|
}
|
||||||
|
PRINTF("FABDEBUG> \tDone reading.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void printUnicastAddressList(NtPIpAdapterUnicastAddress addr) {
|
||||||
|
const char * sep = "";
|
||||||
|
for(; addr; addr=addr->Next) {
|
||||||
|
PRINTF("%s%s", sep, weaken(inet_ntoa)(
|
||||||
|
((struct sockaddr_in *)(addr->Address.lpSockaddr))->sin_addr));
|
||||||
|
if (!sep[0]) {
|
||||||
|
sep=", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int insertAdapterName(NtPIpAdapterAddresses aa) {
|
||||||
|
char name[IFNAMSIZ];
|
||||||
|
int i;
|
||||||
|
int sfx;
|
||||||
|
|
||||||
|
memset(name, 0, sizeof(name));
|
||||||
|
/* On Windows, wchar_t is 16 bit, Linux is 32 bit, cannot use wcstombs() */
|
||||||
|
weaken(WideCharToMultiByte)(0, 0, aa->FriendlyName, -1, name, IFNAMSIZ, NULL, NULL);
|
||||||
|
|
||||||
|
/* Ensure the name is unique */
|
||||||
|
for (sfx = 0; sfx < 10; ++sfx) {
|
||||||
|
i = findAdapterByName(name);
|
||||||
|
if (i != -1) {
|
||||||
|
/* Found a duplicate */
|
||||||
|
name[strlen(name)-1] = '0' + sfx;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Unique */
|
||||||
|
for (i = 0; i < MAX_INTERFACES; ++i) {
|
||||||
|
if (theAdapterName[i].addresses == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == MAX_INTERFACES) {
|
||||||
|
/* Too many interfaces */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
strncpy(theAdapterName[i].name, name, IFNAMSIZ-1);
|
||||||
|
theAdapterName[i].name[IFNAMSIZ-1] = '\0';
|
||||||
|
theAdapterName[i].addresses = aa;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
/* Reached max of 10 duplicates */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
textwindows int ioctl_siocgifconf_nt(int fd, struct ifconf *ifc) {
|
||||||
|
NtPIpAdapterAddresses aa;
|
||||||
|
struct ifreq *ptr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
PRINTF("---------------------------------------\n");
|
||||||
|
PRINTF("Sizeof() = %d\n", sizeof(NtIpAdapterAddresses));
|
||||||
|
PRINTF("Next = %d\n", offsetof(NtIpAdapterAddresses, Next));
|
||||||
|
PRINTF("AdapterName = %d\n", offsetof(NtIpAdapterAddresses, AdapterName));
|
||||||
|
PRINTF("FirstUnicastAddress = %d\n", offsetof(NtIpAdapterAddresses, FirstUnicastAddress));
|
||||||
|
PRINTF("FirstAnycastAddress = %d\n", offsetof(NtIpAdapterAddresses, FirstAnycastAddress));
|
||||||
|
PRINTF("FirstMulticastAddress = %d\n", offsetof(NtIpAdapterAddresses, FirstMulticastAddress));
|
||||||
|
PRINTF("FirstDnsServerAddress = %d\n", offsetof(NtIpAdapterAddresses, FirstDnsServerAddress));
|
||||||
|
PRINTF("DnsSuffix = %d\n", offsetof(NtIpAdapterAddresses, DnsSuffix));
|
||||||
|
PRINTF("Description = %d\n", offsetof(NtIpAdapterAddresses, Description));
|
||||||
|
PRINTF("FriendlyName = %d\n", offsetof(NtIpAdapterAddresses, FriendlyName));
|
||||||
|
|
||||||
|
PRINTF("OperStatus = %d\n", offsetof(NtIpAdapterAddresses, OperStatus));
|
||||||
|
PRINTF("Flags = %d\n", offsetof(NtIpAdapterAddresses, Flags));
|
||||||
|
PRINTF("---------------------------------------\n");
|
||||||
|
|
||||||
|
if (theHostAdapterAddress) {
|
||||||
|
freeAdapterInfo();
|
||||||
|
}
|
||||||
|
if (_readAdapterAddresses() == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ptr = ifc->ifc_req, aa = theHostAdapterAddress;
|
||||||
|
(aa != NULL) && ((char *)(ptr+1) - ifc->ifc_buf) < ifc->ifc_len;
|
||||||
|
aa = aa->Next, ptr++) {
|
||||||
|
|
||||||
|
i = insertAdapterName(aa);
|
||||||
|
if (i == -1) {
|
||||||
|
PRINTF("FABDEBUG> Too many adapters\n");
|
||||||
|
freeAdapterInfo();
|
||||||
|
return enomem();
|
||||||
|
}
|
||||||
|
strncpy(ptr->ifr_name, theAdapterName[i].name, IFNAMSIZ-1);
|
||||||
|
ptr->ifr_name[IFNAMSIZ-1]='\0';
|
||||||
|
|
||||||
|
PRINTF("FABDEBUG> Adapter name = %s\n", ptr->ifr_name);
|
||||||
|
if (aa->FirstUnicastAddress) {
|
||||||
|
ptr->ifr_addr = *aa->FirstUnicastAddress->Address.lpSockaddr; /* Windows sockaddr is compatible with Linux */
|
||||||
|
PRINTF("FABDEBUG> \tIP=");
|
||||||
|
printUnicastAddressList(aa->FirstUnicastAddress);
|
||||||
|
PRINTF("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ifc->ifc_len = (char *)ptr - ifc->ifc_buf;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Performs the SIOCGIFADDR operation */
|
||||||
|
int ioctl_siocgifaddr_nt(int fd, struct ifreq *ifr) {
|
||||||
|
NtPIpAdapterAddresses aa;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = findAdapterByName(ifr->ifr_name);
|
||||||
|
if (i == -1) {
|
||||||
|
PRINTF("FABDEBUG> Bad adapter\n");
|
||||||
|
return ebadf();
|
||||||
|
}
|
||||||
|
|
||||||
|
aa = theAdapterName[i].addresses;
|
||||||
|
if (aa->FirstUnicastAddress) {
|
||||||
|
ifr->ifr_addr = *aa->FirstUnicastAddress->Address.lpSockaddr; /* Windows sockaddr is compatible with Linux */
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Performs the SIOCGIFFLAGS operation */
|
||||||
|
int ioctl_siocgifflags_nt(int fd, struct ifreq *ifr) {
|
||||||
|
NtPIpAdapterAddresses aa;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = findAdapterByName(ifr->ifr_name);
|
||||||
|
if (i == -1) {
|
||||||
|
PRINTF("FABDEBUG> Bad adapter\n");
|
||||||
|
return ebadf();
|
||||||
|
}
|
||||||
|
|
||||||
|
aa = theAdapterName[i].addresses;
|
||||||
|
ifr->ifr_flags = 0;
|
||||||
|
|
||||||
|
/* Flags to consider:
|
||||||
|
* IFF_UP
|
||||||
|
* IFF_BROADCAST ** TODO: We need to validate
|
||||||
|
* IFF_LOOPBACK
|
||||||
|
* IFF_POINTOPOINT
|
||||||
|
* IFF_RUNNING ** Same as IFF_UP for now
|
||||||
|
* IFF_PROMISC ** NOT SUPPORTED, unknown how to retrieve it
|
||||||
|
*/
|
||||||
|
if (aa->OperStatus == IfOperStatusUp) ifr->ifr_flags |= IFF_UP | IFF_RUNNING;
|
||||||
|
if (aa->IfType == NT_IF_TYPE_PPP) ifr->ifr_flags |= IFF_POINTOPOINT;
|
||||||
|
//if (aa->TunnelType != TUNNEL_TYPE_NONE) ifr->ifr_flags |= IFF_POINTOPOINT;
|
||||||
|
if (aa->IfType == NT_IF_TYPE_SOFTWARE_LOOPBACK) ifr->ifr_flags |= IFF_LOOPBACK;
|
||||||
|
if (aa->FirstPrefix != NULL) ifr->ifr_flags |= IFF_BROADCAST;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,8 @@
|
||||||
|
|
||||||
int ioctl_default(int, uint64_t, void *) hidden;
|
int ioctl_default(int, uint64_t, void *) hidden;
|
||||||
int ioctl_siocgifconf_nt(int, struct ifconf *) hidden;
|
int ioctl_siocgifconf_nt(int, struct ifconf *) hidden;
|
||||||
//int ioctl_siocgifaddr_nt(int, struct ifconf *) hidden;
|
int ioctl_siocgifaddr_nt(int, struct ifreq *) hidden;
|
||||||
|
int ioctl_siocgifflags_nt(int, struct ifreq *) hidden;
|
||||||
|
|
||||||
static int ioctl_siocgifconf_sysv(int fd, struct ifconf *ifc) {
|
static int ioctl_siocgifconf_sysv(int fd, struct ifconf *ifc) {
|
||||||
if (IsBsd()) {
|
if (IsBsd()) {
|
||||||
|
@ -131,8 +132,7 @@ int ioctl_siocgifaddr(int fd, void *ifr) {
|
||||||
if (!IsWindows()) {
|
if (!IsWindows()) {
|
||||||
return ioctl_siocgifaddr_sysv(fd, SIOCGIFADDR, (struct ifreq *)ifr);
|
return ioctl_siocgifaddr_sysv(fd, SIOCGIFADDR, (struct ifreq *)ifr);
|
||||||
} else {
|
} else {
|
||||||
return enotsup();
|
return ioctl_siocgifaddr_nt(fd, (struct ifreq *)ifr);
|
||||||
//return ioctl_siocgifaddr_nt(fd, ifc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +168,6 @@ int ioctl_siocgifflags(int fd, void *ifr) {
|
||||||
/* Both BSD and Linux are for once compatible here... */
|
/* Both BSD and Linux are for once compatible here... */
|
||||||
return ioctl_default(fd, SIOCGIFFLAGS, ifr);
|
return ioctl_default(fd, SIOCGIFFLAGS, ifr);
|
||||||
} else {
|
} else {
|
||||||
return enotsup();
|
return ioctl_siocgifflags_nt(fd, (struct ifreq *)ifr);
|
||||||
//return ioctl_siocgifflags_nt(fd, ifc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
/* ioctl(SIOCGIFCONFIG) uses GetAdaptersAddresses as weak ref */
|
/* ioctl(SIOCGIFCONFIG) uses GetAdaptersAddresses as weak ref */
|
||||||
STATIC_YOINK("GetAdaptersAddresses");
|
STATIC_YOINK("GetAdaptersAddresses");
|
||||||
|
STATIC_YOINK("WideCharToMultiByte");
|
||||||
|
|
||||||
textwindows int sys_socket_nt(int family, int type, int protocol) {
|
textwindows int sys_socket_nt(int family, int type, int protocol) {
|
||||||
int64_t h;
|
int64_t h;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue