Major refactor of the Windows implementation of ioctl for SIOCGIFxxxx

methods.
This commit is contained in:
Fabrizio Bertocci 2021-06-23 13:58:43 +02:00
parent 5704b03d26
commit b3b85c2f96
94 changed files with 1130 additions and 296 deletions

View file

@ -27,355 +27,407 @@
#include "libc/nt/winsock.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/nt/struct/ipadapteraddresses.h"
#include "libc/bits/weaken.h"
#include "libc/str/str.h"
#include "libc/assert.h"
//#include "libc/nt/windows.h" /* Needed for WideCharToMultiByte */
// TODO: Remove me
#include "libc/stdio/stdio.h"
#define PRINTF weaken(printf)
#define MAX_INTERFACES 32
/* Maximum number of unicast addresses handled for each interface */
#define MAX_UNICAST_ADDR 32
#define MAX_NAME_CLASH ((int)('z'-'a')) /* Allow a..z */
static int insertAdapterName(NtPIpAdapterAddresses aa);
static int insertAdapterName(NtIpAdapterAddresses *aa);
/* Reference:
* - 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
* - WSAIoctl man page: https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsaioctl
* - Using SIOCGIFCONF in Win32: https://docs.microsoft.com/en-us/windows/win32/winsock/using-unix-ioctls-in-winsock
*/
struct HostAdapterInfoNode {
struct HostAdapterInfoNode * next;
char name[IFNAMSIZ]; /* Obtained from FriendlyName */
struct sockaddr unicast;
struct sockaddr netmask;
struct sockaddr broadcast;
short flags;
} *__hostInfo;
/* Design note:
* 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 */
short flags; /* Holds the same value as ifr_flags */
};
NtIpAdapterAddresses * theHostAdapterAddress;
struct HostAdapterDesc theAdapterName[MAX_INTERFACES];
/* Given a short adapter name, look into theAdapterName to see if there is
* an adapter with the same name. Returns the index of theAdapterName
* if found, or -1 if not found
*/
static int findAdapterByName(const char *name) {
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;
/* Frees all the nodes of the _hostInfo */
static void freeHostInfo() {
struct HostAdapterInfoNode *next, *node = __hostInfo;
while(node) {
next = node->next;
weaken(free)(node);
node = next;
}
__hostInfo = NULL;
}
static void freeAdapterInfo(void) {
if (theHostAdapterAddress) {
/* Free any existing adapter informations */
weaken(free)(theHostAdapterAddress);
theHostAdapterAddress = NULL;
memset(theAdapterName, 0, sizeof(theAdapterName));
/* Given a short adapter name, look into __hostInfo to see if there is
* an adapter with the same name. Returns the pointer to the HostAdapterInfoNode
* if found, or NULL if not found
*/
static struct HostAdapterInfoNode *findAdapterByName(const char *name) {
struct HostAdapterInfoNode *node = __hostInfo;
while(node) {
if (!strncmp(name, node->name, IFNAMSIZ)) {
/* Found */
return node;
}
node=node->next;
}
/* Not found */
return NULL;
}
/* Creates a new HostAdapterInfoNode object, initializes it from
* the given adapter, unicast address and address prefixes
* and insert it in the __hostInfo.
* Increments the pointers to the unicast addresses and
* the address prefixes
* Returns NULL if an error occurred or the newly created
* HostAdapterInfoNode object (last in the list)
*/
struct HostAdapterInfoNode *appendHostInfo(
struct HostAdapterInfoNode *parentInfoNode,
const char *baseName, /* Max length = IFNAMSIZ-1 */
const NtIpAdapterAddresses *aa, /* Top level adapter object being processed */
NtIpAdapterUnicastAddress **ptrUA, /* Ptr to ptr to unicast address list node */
NtIpAdapterPrefix **ptrAP, /* Ptr to ptr to Adapter prefix list node */
int count) { /* count is used to create a unique name in case of alias */
/* Sets theHostAdapterAddress.
* Returns -1 in case of failure (setting errno appropriately), 0 if success */
static int _readAdapterAddresses(void) {
NtPIpAdapterAddresses aa;
uint32_t size, rc;
struct HostAdapterInfoNode *temp;
struct HostAdapterInfoNode *node;
struct sockaddr_in tempAddr;
int attemptNum;
PRINTF("FABDEBUG> \t\t\tappendHostInfo:\n");
node = weaken(calloc)(1, sizeof(*node));
if (!node) {
PRINTF("FABDEBUG> \t\t\tMALLOC FAILED\n");
errno = ENOMEM;
return NULL;
}
memcpy(node->name, baseName, IFNAMSIZ);
PRINTF("FABDEBUG> \t\t\tnodeAllocated, name=%s\n", node->name);
/* Are there more than a single unicast address ? */
if (count > 0 || ((*ptrUA)->Next != NULL)) {
/* Yes, compose it using <baseName>:<count> */
size_t nameLen = strlen(node->name);
if (nameLen+2 > IFNAMSIZ-2) {
/* Appending the ":x" will exceed the size, need to chop the end */
nameLen -= 2;
}
node->name[nameLen-2] = ':';
node->name[nameLen-1] = '0'+count;
node->name[nameLen] = '\0';
PRINTF("FABDEBUG> \t\t\tComputing multi-unicast name: '%s'\n", node->name);
}
/* Is there a name clash with other interfaces? */
PRINTF("FABDEBUG> \t\t\tFinding name clashes\n");
for (attemptNum=0; attemptNum < MAX_NAME_CLASH; ++attemptNum) {
temp = findAdapterByName(node->name);
if (!temp) {
break;
} else {
/* Yes, this name has been already used, append an extra
* character to resolve conflict. Note since the max length
* of the string now is IFNAMSIZ-2, we have just enough space for this.
* E.g. 'Ethernet_1' -> 'Ethernet_1a'
*/
size_t pos = strlen(node->name);
PRINTF("FABDEBUG> \t\t\t** NAME CLASH name=%s, attemptNum=%d\n", temp->name, attemptNum);
node->name[pos] = 'a' + attemptNum;
node->name[pos+1] = '\0';
/* Try again */
}
}
if (attemptNum == MAX_NAME_CLASH) {
/* Cannot resolve the conflict */
PRINTF("FABDEBUG> \t\t\tReached max clash attempts...\n");
weaken(free)(node);
errno = EEXIST;
return NULL;
}
PRINTF("FABDEBUG> \t\t\tappendHostInfo: computed name='%s'\n", node->name);
/* Finally we got a unique short and friendly name */
node->unicast = *((*ptrUA)->Address.lpSockaddr);
if (*ptrUA == aa->FirstUnicastAddress) {
short flags;
int i;
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
/* This is the first unicast address of this interface
* calculate the flags for this adapter. Flags to consider:
* IFF_UP
* IFF_BROADCAST ** TODO: We need to validate
* IFF_LOOPBACK
* IFF_POINTOPOINT
* IFF_MULTICAST
* IFF_RUNNING ** Same as IFF_UP for now
* IFF_PROMISC ** NOT SUPPORTED, unknown how to retrieve it
*/
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();
}
flags = 0;
if (aa->OperStatus == kNtIfOperStatusUp) flags |= IFF_UP | IFF_RUNNING;
if (aa->IfType == kNtIfTypePpp) flags |= IFF_POINTOPOINT;
//if (aa->TunnelType != TUNNEL_TYPE_NONE) flags |= IFF_POINTOPOINT;
if (aa->NoMulticast == 0) flags |= IFF_MULTICAST;
if (aa->IfType == kNtIfTypeSoftwareLoopback) flags |= IFF_LOOPBACK;
if (aa->FirstPrefix != NULL) flags |= IFF_BROADCAST;
node->flags = flags;
} else {
/* Copy from previous node */
node->flags = parentInfoNode->flags;
}
/* 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();
}
/* Process the prefix and extract the netmask and broadcast */
/* According to the doc:
* ... On Windows Vista and later, the linked IP_ADAPTER_PREFIX structures pointed to
* by the FirstPrefix member include three IP adapter prefixes for each IP address
* assigned to the adapter. These include the host IP address prefix, the subnet IP
* address prefix, and the subnet broadcast IP address prefix. In addition, for each
* adapter there is a multicast address prefix and a broadcast address prefix.
*
* For example, interface "Ethernet", with 2 unicast addresses:
* - 192.168.1.84
* - 192.168.5.99
* The Prefix list has 8 elements:
* #1: 192.168.1.0/24 <- Network, use the PrefixLength for netmask
* #2: 192.168.1.84/32 <- Host IP
* #3: 192.168.1.255/32 <- Subnet broadcast
*
* #4: 192.168.5.0/24 <- Network
* #5: 192.168.5.99/32 <- Host IP
* #6: 192.168.5.255/32 <- Subnet broadcast
*
* #7: 224.0.0.0/4 <- Multicast
* #8: 255.255.255.255/32 <- Broadcast
*/
/* Iterate through all the adapters and populate theAdapterName */
for (aa = theHostAdapterAddress; aa != NULL; aa = aa->Next) {
i = insertAdapterName(aa);
if (i == -1) {
PRINTF("FABDEBUG> Too many adapters\n");
freeAdapterInfo();
return enomem();
}
/* Netmask */
memset(&tempAddr, 0, sizeof(tempAddr));
tempAddr.sin_family = AF_INET;
tempAddr.sin_addr.s_addr = (uint32_t)((1LLU << (*ptrAP)->PrefixLength) - 1LLU);
memcpy(&node->netmask, &tempAddr, sizeof(tempAddr));
/* Calculate the flags for this adapter. Flags to consider:
* IFF_UP
* IFF_BROADCAST ** TODO: We need to validate
* IFF_LOOPBACK
* IFF_POINTOPOINT
* IFF_MULTICAST
* IFF_RUNNING ** Same as IFF_UP for now
* IFF_PROMISC ** NOT SUPPORTED, unknown how to retrieve it
*/
flags = 0;
if (aa->OperStatus == IfOperStatusUp) flags |= IFF_UP | IFF_RUNNING;
if (aa->IfType == NT_IF_TYPE_PPP) flags |= IFF_POINTOPOINT;
//if (aa->TunnelType != TUNNEL_TYPE_NONE) flags |= IFF_POINTOPOINT;
if (aa->NoMulticast == 0) flags |= IFF_MULTICAST;
if (aa->IfType == NT_IF_TYPE_SOFTWARE_LOOPBACK) flags |= IFF_LOOPBACK;
if (aa->FirstPrefix != NULL) flags |= IFF_BROADCAST;
*ptrAP = (*ptrAP)->Next;
*ptrAP = (*ptrAP)->Next; /* Skip over Host IP */
/* Broadcast - Broadcast address should be detectable though the FirstPrefix
* linked list
*/
flags |= IFF_BROADCAST; /* Assume yes for all the interfaces */
/* Broadcast */
node->broadcast = *((*ptrAP)->Address.lpSockaddr);
*ptrAP = (*ptrAP)->Next;
theAdapterName[i].flags = flags;
}
PRINTF("FABDEBUG> \tDone reading.\n");
return 0;
/* Move pointer to Unicast Address record */
*ptrUA = (*ptrUA)->Next;
/* Append this node to the last node (if any) */
if (parentInfoNode) {
parentInfoNode->next = node;
}
/* Success */
return node;
}
/* Returns -1 in case of failure */
static int createHostInfo(NtIpAdapterAddresses *firstAdapter) {
NtIpAdapterAddresses *aa;
NtIpAdapterUnicastAddress *ua;
NtIpAdapterPrefix *ap;
struct HostAdapterInfoNode *node = NULL;
char baseName[IFNAMSIZ];
char name[IFNAMSIZ];
int count, i;
#if 1
/* __hostInfo must be empty */
assert(__hostInfo == NULL);
assert(weaken(tprecode16to8));
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=", ";
}
for (aa = firstAdapter; aa; aa = aa->Next) {
/* Skip all the interfaces with no address and the ones that are not AF_INET */
if (!aa->FirstUnicastAddress ||
aa->FirstUnicastAddress->Address.lpSockaddr->sa_family != AF_INET) {
continue;
}
/* Use max IFNAMSIZ-1 chars, leave the last char for eventual conficts */
tprecode16to8(baseName, IFNAMSIZ-1, aa->FriendlyName);
baseName[IFNAMSIZ-2] = '\0';
/* Replace any space with a '_' */
for (i = 0; i < IFNAMSIZ-2; ++i) {
if (baseName[i] == ' ') baseName[i] = '_';
if (!baseName[i]) break;
}
PRINTF("FABDEBUG> \tcreateHostInfo: processing Win interface with baseName='%s'\n", baseName);
for (count = 0, ua = aa->FirstUnicastAddress, ap = aa->FirstPrefix;
(ua != NULL) && (count < MAX_UNICAST_ADDR);
++count) {
node = appendHostInfo(node, baseName, aa, &ua, &ap, count);
if (!node) {
goto err;
}
if (!__hostInfo) __hostInfo = node;
PRINTF("FABDEBUG> \t\tcreateHostInfo: added interface='%s'\n", node->name);
}
/* Note: do we need to process the remaining adapter prefix?
* ap - points to broadcast addr
* ap->Next - points to interface multicast addr
* Ignoring them for now
*/
}
return 0;
err:
freeHostInfo(__hostInfo);
return -1;
}
#endif
static int readAdapterAddresses(void) {
uint32_t size, rc;
NtIpAdapterAddresses * aa = NULL;
PRINTF("FABDEBUG> _readAdapterAddresses:\n");
static int insertAdapterName(NtPIpAdapterAddresses aa) {
char name[IFNAMSIZ];
int i;
int sfx;
assert(weaken(GetAdaptersAddresses));
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);
/* Calculate the required data size
* Note: alternatively you can use AF_UNSPEC to also return IPv6 interfaces
*/
rc = weaken(GetAdaptersAddresses)(AF_INET,
kNtGaaFlagSkipAnycast | kNtGaaFlagSkipMulticast | kNtGaaFlagSkipDnsServer | kNtGaaFlagIncludePrefix,
NULL, /* Reserved */
NULL, /* Ptr */
&size);
if (rc != kNtErrorBufferOverflow) {
PRINTF("FABDEBUG> \tGetAdaptersAddresses failed with error %d\n", WSAGetLastError());
ebadf();
goto err;
}
PRINTF("FABDEBUG> \tsize required=%lu, allocating...\n", size);
/* 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;
aa = (NtIpAdapterAddresses *)weaken(malloc)(size);
if (!aa) {
PRINTF("FABDEBUG> \tmalloc failed\n");
enomem();
goto err;
}
/* Re-run GetAdaptersAddresses this time with a valid buffer */
rc = weaken(GetAdaptersAddresses)(AF_INET,
kNtGaaFlagSkipAnycast | kNtGaaFlagSkipMulticast | kNtGaaFlagSkipDnsServer | kNtGaaFlagIncludePrefix,
//kNtGaaFlagIncludePrefix,
NULL,
aa,
&size);
if (rc != kNtErrorSuccess) {
PRINTF("FABDEBUG> \tGetAdaptersAddresses failed %d\n", WSAGetLastError());
efault();
goto err;
}
if (createHostInfo(aa) == -1) {
PRINTF("FABDEBUG> \tFailed to createHostInfo\n");
goto err;
}
PRINTF("FABDEBUG> \tDone reading.\n");
{
struct HostAdapterInfoNode *foo = __hostInfo;
while (foo) {
PRINTF("FABDEBUG>>>>>>> %s - %s\n", foo->name,
weaken(inet_ntoa)(
((struct sockaddr_in *)(&foo->unicast))->sin_addr));
foo = foo->next;
}
/* Reached max of 10 duplicates */
return -1;
}
weaken(free)(aa);
return 0;
err:
if (aa) {
weaken(free)(aa);
}
freeHostInfo();
return -1;
}
/* Returns the index in theAdapterName if found or -1 if
* an error occurred
*/
static int findOrInitAdapter(const char *name) {
int i;
if (!theHostAdapterAddress) {
/* Never invoked GetAdaptersAddresses */
if (_readAdapterAddresses() == -1) {
return -1;
}
}
i = findAdapterByName(name);
if (i == -1) {
PRINTF("FABDEBUG> Bad adapter\n");
return ebadf();
}
return i;
}
textwindows int ioctl_siocgifconf_nt(int fd, struct ifconf *ifc) {
NtPIpAdapterAddresses aa;
struct ifreq *ptr;
int i;
NtIpAdapterAddresses *aa;
struct HostAdapterInfoNode *node;
struct ifreq *ptr;
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));
if (__hostInfo) {
freeHostInfo();
}
PRINTF("OperStatus = %d\n", offsetof(NtIpAdapterAddresses, OperStatus));
PRINTF("Flags = %d\n", offsetof(NtIpAdapterAddresses, Flags));
PRINTF("---------------------------------------\n");
if (readAdapterAddresses() == -1) {
return -1;
}
if (theHostAdapterAddress) {
freeAdapterInfo();
}
if (_readAdapterAddresses() == -1) {
return -1;
}
for (ptr = ifc->ifc_req, node = __hostInfo;
(((char *)(ptr+1) - ifc->ifc_buf) < ifc->ifc_len) && node;
ptr++, node = node->next) {
memcpy(ptr->ifr_name, node->name, IFNAMSIZ);
memcpy(&ptr->ifr_addr, &node->unicast, sizeof(struct sockaddr));
for (ptr = ifc->ifc_req, i=0;
((char *)(ptr+1) - ifc->ifc_buf) < ifc->ifc_len;
++i, ptr++) {
aa = theAdapterName[i].addresses;
if (!aa) {
break;
}
memcpy(ptr->ifr_name, theAdapterName[i].name, IFNAMSIZ);
PRINTF("FABDEBUG> #%d: Adapter name = %s\n", i, 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;
PRINTF("FABDEBUG> Adapter name = '%s'. IP=%s\n", ptr->ifr_name,
weaken(inet_ntoa)(((struct sockaddr_in *)(&ptr->ifr_addr))->sin_addr));
PRINTF("FABDEBUG> '%s'. BR=%s\n", ptr->ifr_name,
weaken(inet_ntoa)(((struct sockaddr_in *)&node->broadcast)->sin_addr));
}
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;
struct HostAdapterInfoNode *node;
i = findOrInitAdapter(ifr->ifr_name);
if (i == -1) {
return -1;
}
aa = theAdapterName[i].addresses;
if (aa->FirstUnicastAddress) {
ifr->ifr_addr = *aa->FirstUnicastAddress->Address.lpSockaddr; /* Windows sockaddr is compatible with Linux */
}
return 0;
node = findAdapterByName(ifr->ifr_name);
if (!node) {
return ebadf();
}
memcpy(&ifr->ifr_addr, &node->unicast, sizeof(struct sockaddr));
return 0;
}
/* Performs the SIOCGIFFLAGS operation */
int ioctl_siocgifflags_nt(int fd, struct ifreq *ifr) {
int i;
i = findOrInitAdapter(ifr->ifr_name);
if (i == -1) {
return -1;
}
struct HostAdapterInfoNode *node;
PRINTF(">>>>CAZZO=%d - %d\n", i, theAdapterName[i].flags);
ifr->ifr_flags = theAdapterName[i].flags;
return 0;
node = findAdapterByName(ifr->ifr_name);
if (!node) {
return ebadf();
}
ifr->ifr_flags = node->flags;
return 0;
}
/* Performs the SIOCGIFNETMASK operation */
int ioctl_siocgifnetmask_nt(int fd, struct ifreq *ifr) {
NtPIpAdapterAddresses aa;
int i;
struct HostAdapterInfoNode *node;
i = findOrInitAdapter(ifr->ifr_name);
if (i == -1) {
return -1;
}
PRINTF("FABDEBUG>>>> NETMASK\n");
aa = theAdapterName[i].addresses;
/* According to the doc:
* ... On Windows Vista and later, the linked IP_ADAPTER_PREFIX structures pointed to
* by the FirstPrefix member include three IP adapter prefixes for each IP address
* assigned to the adapter. These include the host IP address prefix, the subnet IP
* address prefix, and the subnet broadcast IP address prefix. In addition, for each
* adapter there is a multicast address prefix and a broadcast address prefix.
*
* So, in short, for each of the assigned addresses, the IP_ADAPTER_PREFIX objects are:
* #0: Host IP Address
* #1: Subnet
* #2: Broadcast
* #3: Multicast
* #4: Broadcast
*/
if (aa->FirstPrefix) {
int count;
NtPIpAdapterPrefix prefix;
for (count=0, prefix=aa->FirstPrefix; prefix; prefix=prefix->Next, ++count) {
PRINTF("FABDEBUG>>>>\t%d: %s/%d\n", count, weaken(inet_ntoa)(
((struct sockaddr_in *)(prefix->Address.lpSockaddr))->sin_addr), prefix->PrefixLength);
if (count == 4) {
ifr->ifr_netmask = *prefix->Address.lpSockaddr;
}
}
}
return 0;
node = findAdapterByName(ifr->ifr_name);
if (!node) {
return ebadf();
}
memcpy(&ifr->ifr_netmask, &node->netmask, sizeof(struct sockaddr));
return 0;
}
/* Performs the SIOCGIFBRDADDR operation */
int ioctl_siocgifbrdaddr_nt(int fd, struct ifreq *ifr) {
struct HostAdapterInfoNode *node;
node = findAdapterByName(ifr->ifr_name);
if (!node) {
return ebadf();
}
memcpy(&ifr->ifr_broadaddr, &node->broadcast, sizeof(struct sockaddr));
return 0;
}

View file

@ -38,6 +38,7 @@ int ioctl_siocgifconf_nt(int, struct ifconf *) hidden;
int ioctl_siocgifaddr_nt(int, struct ifreq *) hidden;
int ioctl_siocgifflags_nt(int, struct ifreq *) hidden;
int ioctl_siocgifnetmask_nt(int, struct ifreq *) hidden;
int ioctl_siocgifbrdaddr_nt(int, struct ifreq *) hidden;
static int ioctl_siocgifconf_sysv(int fd, struct ifconf *ifc) {
if (IsBsd()) {
@ -149,8 +150,7 @@ int ioctl_siocgifbrdaddr(int fd, void *ifr) {
if (!IsWindows()) {
return ioctl_siocgifaddr_sysv(fd, SIOCGIFBRDADDR, (struct ifreq *)ifr);
} else {
return enotsup();
//return ioctl_siocgifbrdaddr_nt(fd, ifc);
return ioctl_siocgifbrdaddr_nt(fd, (struct ifreq *)ifr);
}
}

42
libc/nt/iphlpapi.h Normal file
View file

@ -0,0 +1,42 @@
#ifndef COSMOPOLITAN_LIBC_NT_IPHLPAPI_H_
#define COSMOPOLITAN_LIBC_NT_IPHLPAPI_H_
#include "libc/nt/struct/ipadapteraddresses.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/* ░░░░
cosmopolitan § new technology » ip helper API
*/
uint32_t GetAdaptersAddresses(
uint32_t Family,
uint32_t Flags,
void * Reserved,
NtIpAdapterAddresses *AdapterAddresses,
uint32_t *SizePointer);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NT_IPHLPAPI_H_ */

View file

@ -0,0 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_AddIPAddress,AddIPAddress,0
.text.windows
AddIPAddress:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_AddIPAddress(%rip),%rax
jmp __sysv2nt6
.endfn AddIPAddress,globl
.previous

View file

@ -0,0 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_AllocateAndGetTcpExTableFromStack,AllocateAndGetTcpExTableFromStack,0
.text.windows
AllocateAndGetTcpExTableFromStack:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_AllocateAndGetTcpExTableFromStack(%rip),%rax
jmp __sysv2nt6
.endfn AllocateAndGetTcpExTableFromStack,globl
.previous

View file

@ -0,0 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_AllocateAndGetUdpExTableFromStack,AllocateAndGetUdpExTableFromStack,0
.text.windows
AllocateAndGetUdpExTableFromStack:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_AllocateAndGetUdpExTableFromStack(%rip),%rax
jmp __sysv2nt6
.endfn AllocateAndGetUdpExTableFromStack,globl
.previous

View file

@ -0,0 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_CancelIPChangeNotify,CancelIPChangeNotify,0
.text.windows
CancelIPChangeNotify:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_CancelIPChangeNotify(%rip)
leave
ret
.endfn CancelIPChangeNotify,globl
.previous

View file

@ -0,0 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_CaptureInterfaceHardwareCrossTimestamp,CaptureInterfaceHardwareCrossTimestamp,0
.text.windows
CaptureInterfaceHardwareCrossTimestamp:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_CaptureInterfaceHardwareCrossTimestamp(%rip),%rax
jmp __sysv2nt
.endfn CaptureInterfaceHardwareCrossTimestamp,globl
.previous

View file

@ -0,0 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_CreateIpForwardEntry,CreateIpForwardEntry,0
.text.windows
CreateIpForwardEntry:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_CreateIpForwardEntry(%rip)
leave
ret
.endfn CreateIpForwardEntry,globl
.previous

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_CreateIpNetEntry,CreateIpNetEntry,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_CreatePersistentTcpPortReservation,CreatePersistentTcpPortReservation,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_CreatePersistentUdpPortReservation,CreatePersistentUdpPortReservation,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_CreateProxyArpEntry,CreateProxyArpEntry,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_DeleteIPAddress,DeleteIPAddress,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_DeleteIpForwardEntry,DeleteIpForwardEntry,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_DeleteIpNetEntry,DeleteIpNetEntry,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_DeletePersistentTcpPortReservation,DeletePersistentTcpPortReservation,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_DeletePersistentUdpPortReservation,DeletePersistentUdpPortReservation,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_DeleteProxyArpEntry,DeleteProxyArpEntry,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_DisableMediaSense,DisableMediaSense,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_EnableRouter,EnableRouter,0

View file

@ -0,0 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_FlushIpNetTable,FlushIpNetTable,0
.text.windows
FlushIpNetTable:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_FlushIpNetTable(%rip)
leave
ret
.endfn FlushIpNetTable,globl
.previous

View file

@ -0,0 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetAdapterIndex,GetAdapterIndex,0
.text.windows
GetAdapterIndex:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_GetAdapterIndex(%rip),%rax
jmp __sysv2nt
.endfn GetAdapterIndex,globl
.previous

View file

@ -0,0 +1,14 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetAdapterOrderMap,GetAdapterOrderMap,0
.text.windows
GetAdapterOrderMap:
push %rbp
mov %rsp,%rbp
.profilable
sub $32,%rsp
call *__imp_GetAdapterOrderMap(%rip)
leave
ret
.endfn GetAdapterOrderMap,globl
.previous

View file

@ -0,0 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetAdaptersAddresses,GetAdaptersAddresses,67
.text.windows
GetAdaptersAddresses:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_GetAdaptersAddresses(%rip),%rax
jmp __sysv2nt6
.endfn GetAdaptersAddresses,globl
.previous

View file

@ -0,0 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetAdaptersInfo,GetAdaptersInfo,0
.text.windows
GetAdaptersInfo:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_GetAdaptersInfo(%rip),%rax
jmp __sysv2nt
.endfn GetAdaptersInfo,globl
.previous

View file

@ -0,0 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetBestInterface,GetBestInterface,0
.text.windows
GetBestInterface:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_GetBestInterface(%rip),%rax
jmp __sysv2nt
.endfn GetBestInterface,globl
.previous

View file

@ -0,0 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetBestInterfaceEx,GetBestInterfaceEx,0
.text.windows
GetBestInterfaceEx:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_GetBestInterfaceEx(%rip),%rax
jmp __sysv2nt
.endfn GetBestInterfaceEx,globl
.previous

View file

@ -0,0 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetBestRoute,GetBestRoute,0
.text.windows
GetBestRoute:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_GetBestRoute(%rip),%rax
jmp __sysv2nt
.endfn GetBestRoute,globl
.previous

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetExtendedTcpTable,GetExtendedTcpTable,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetExtendedUdpTable,GetExtendedUdpTable,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetFriendlyIfIndex,GetFriendlyIfIndex,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetIcmpStatistics,GetIcmpStatistics,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetIcmpStatisticsEx,GetIcmpStatisticsEx,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetIfEntry,GetIfEntry,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetIfTable,GetIfTable,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetInterfaceActiveTimestampCapabilities,GetInterfaceActiveTimestampCapabilities,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetInterfaceInfo,GetInterfaceInfo,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetInterfaceSupportedTimestampCapabilities,GetInterfaceSupportedTimestampCapabilities,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetIpAddrTable,GetIpAddrTable,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetIpErrorString,GetIpErrorString,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetIpForwardTable,GetIpForwardTable,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetIpNetTable,GetIpNetTable,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetIpStatistics,GetIpStatistics,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetIpStatisticsEx,GetIpStatisticsEx,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetNetworkParams,GetNetworkParams,0

View file

@ -0,0 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetNumberOfInterfaces,GetNumberOfInterfaces,0
.text.windows
GetNumberOfInterfaces:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_GetNumberOfInterfaces(%rip)
leave
ret
.endfn GetNumberOfInterfaces,globl
.previous

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetOwnerModuleFromTcp6Entry,GetOwnerModuleFromTcp6Entry,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetOwnerModuleFromTcpEntry,GetOwnerModuleFromTcpEntry,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetOwnerModuleFromUdp6Entry,GetOwnerModuleFromUdp6Entry,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetOwnerModuleFromUdpEntry,GetOwnerModuleFromUdpEntry,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetPerAdapterInfo,GetPerAdapterInfo,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetPerTcp6ConnectionEStats,GetPerTcp6ConnectionEStats,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetPerTcpConnectionEStats,GetPerTcpConnectionEStats,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetRTTAndHopCount,GetRTTAndHopCount,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetTcp6Table,GetTcp6Table,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetTcp6Table2,GetTcp6Table2,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetTcpStatistics,GetTcpStatistics,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetTcpStatisticsEx,GetTcpStatisticsEx,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetTcpStatisticsEx2,GetTcpStatisticsEx2,0

View file

@ -0,0 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetTcpTable,GetTcpTable,0
.text.windows
GetTcpTable:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_GetTcpTable(%rip),%rax
jmp __sysv2nt
.endfn GetTcpTable,globl
.previous

View file

@ -0,0 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetTcpTable2,GetTcpTable2,0
.text.windows
GetTcpTable2:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_GetTcpTable2(%rip),%rax
jmp __sysv2nt
.endfn GetTcpTable2,globl
.previous

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetUdp6Table,GetUdp6Table,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetUdpStatistics,GetUdpStatistics,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetUdpStatisticsEx,GetUdpStatisticsEx,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetUdpStatisticsEx2,GetUdpStatisticsEx2,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetUdpTable,GetUdpTable,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_GetUniDirectionalAdapterInfo,GetUniDirectionalAdapterInfo,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_IpReleaseAddress,IpReleaseAddress,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_IpRenewAddress,IpRenewAddress,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_LookupPersistentTcpPortReservation,LookupPersistentTcpPortReservation,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_LookupPersistentUdpPortReservation,LookupPersistentUdpPortReservation,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_NhpAllocateAndGetInterfaceInfoFromStack,NhpAllocateAndGetInterfaceInfoFromStack,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_NotifyAddrChange,NotifyAddrChange,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_NotifyRouteChange,NotifyRouteChange,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_ParseNetworkString,ParseNetworkString,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_RegisterInterfaceTimestampConfigChange,RegisterInterfaceTimestampConfigChange,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_ResolveNeighbor,ResolveNeighbor,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_RestoreMediaSense,RestoreMediaSense,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_SendARP,SendARP,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_SetIfEntry,SetIfEntry,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_SetIpForwardEntry,SetIpForwardEntry,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_SetIpNetEntry,SetIpNetEntry,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_SetIpStatistics,SetIpStatistics,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_SetIpStatisticsEx,SetIpStatisticsEx,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_SetIpTTL,SetIpTTL,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_SetPerTcp6ConnectionEStats,SetPerTcp6ConnectionEStats,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_SetPerTcpConnectionEStats,SetPerTcpConnectionEStats,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_SetTcpEntry,SetTcpEntry,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_UnenableRouter,UnenableRouter,0

View file

@ -0,0 +1,2 @@
.include "o/libc/nt/codegen.inc"
.imp iphlpapi,__imp_UnregisterInterfaceTimestampConfigChange,UnregisterInterfaceTimestampConfigChange,0

View file

@ -7798,4 +7798,91 @@ imp 'ReleaseSRWLockShared' ReleaseSRWLockShared kernel32 0 1 # KernelBas
imp 'TryAcquireSRWLockExclusive' TryAcquireSRWLockExclusive kernel32 0 1 # KernelBase
imp 'TryAcquireSRWLockShared' TryAcquireSRWLockShared kernel32 0 1 # KernelBase
imp 'AddIPAddress' AddIPAddress iphlpapi 0 5
imp 'AllocateAndGetTcpExTableFromStack' AllocateAndGetTcpExTableFromStack iphlpapi 0 5
imp 'AllocateAndGetUdpExTableFromStack' AllocateAndGetUdpExTableFromStack iphlpapi 0 5
imp 'CancelIPChangeNotify' CancelIPChangeNotify iphlpapi 0 1
imp 'CaptureInterfaceHardwareCrossTimestamp' CaptureInterfaceHardwareCrossTimestamp iphlpapi 0 2
imp 'CreateIpForwardEntry' CreateIpForwardEntry iphlpapi 0 1
imp 'CreateIpNetEntry' CreateIpNetEntry iphlpapi 0
imp 'CreatePersistentTcpPortReservation' CreatePersistentTcpPortReservation iphlpapi 0
imp 'CreatePersistentUdpPortReservation' CreatePersistentUdpPortReservation iphlpapi 0
imp 'CreateProxyArpEntry' CreateProxyArpEntry iphlpapi 0
imp 'DeleteIPAddress' DeleteIPAddress iphlpapi 0
imp 'DeleteIpForwardEntry' DeleteIpForwardEntry iphlpapi 0
imp 'DeleteIpNetEntry' DeleteIpNetEntry iphlpapi 0
imp 'DeletePersistentTcpPortReservation' DeletePersistentTcpPortReservation iphlpapi 0
imp 'DeletePersistentUdpPortReservation' DeletePersistentUdpPortReservation iphlpapi 0
imp 'DeleteProxyArpEntry' DeleteProxyArpEntry iphlpapi 0
imp 'DisableMediaSense' DisableMediaSense iphlpapi 0
imp 'EnableRouter' EnableRouter iphlpapi 0
imp 'FlushIpNetTable' FlushIpNetTable iphlpapi 0 1
imp 'GetAdapterIndex' GetAdapterIndex iphlpapi 0 2
imp 'GetAdapterOrderMap' GetAdapterOrderMap iphlpapi 0 0
imp 'GetAdaptersAddresses' GetAdaptersAddresses iphlpapi 67 5
imp 'GetAdaptersInfo' GetAdaptersInfo iphlpapi 0 2
imp 'GetBestInterface' GetBestInterface iphlpapi 0 2
imp 'GetBestInterfaceEx' GetBestInterfaceEx iphlpapi 0 2
imp 'GetBestRoute' GetBestRoute iphlpapi 0 3
imp 'GetExtendedTcpTable' GetExtendedTcpTable iphlpapi 0
imp 'GetExtendedUdpTable' GetExtendedUdpTable iphlpapi 0
imp 'GetFriendlyIfIndex' GetFriendlyIfIndex iphlpapi 0
imp 'GetIcmpStatistics' GetIcmpStatistics iphlpapi 0
imp 'GetIcmpStatisticsEx' GetIcmpStatisticsEx iphlpapi 0
imp 'GetIfEntry' GetIfEntry iphlpapi 0
imp 'GetIfTable' GetIfTable iphlpapi 0
imp 'GetInterfaceActiveTimestampCapabilities' GetInterfaceActiveTimestampCapabilities iphlpapi 0
imp 'GetInterfaceInfo' GetInterfaceInfo iphlpapi 0
imp 'GetInterfaceSupportedTimestampCapabilities' GetInterfaceSupportedTimestampCapabilities iphlpapi 0
imp 'GetIpAddrTable' GetIpAddrTable iphlpapi 0
imp 'GetIpErrorString' GetIpErrorString iphlpapi 0
imp 'GetIpForwardTable' GetIpForwardTable iphlpapi 0
imp 'GetIpNetTable' GetIpNetTable iphlpapi 0
imp 'GetIpStatistics' GetIpStatistics iphlpapi 0
imp 'GetIpStatisticsEx' GetIpStatisticsEx iphlpapi 0
imp 'GetNetworkParams' GetNetworkParams iphlpapi 0
imp 'GetNumberOfInterfaces' GetNumberOfInterfaces iphlpapi 0 1
imp 'GetOwnerModuleFromTcp6Entry' GetOwnerModuleFromTcp6Entry iphlpapi 0
imp 'GetOwnerModuleFromTcpEntry' GetOwnerModuleFromTcpEntry iphlpapi 0
imp 'GetOwnerModuleFromUdp6Entry' GetOwnerModuleFromUdp6Entry iphlpapi 0
imp 'GetOwnerModuleFromUdpEntry' GetOwnerModuleFromUdpEntry iphlpapi 0
imp 'GetPerAdapterInfo' GetPerAdapterInfo iphlpapi 0
imp 'GetPerTcp6ConnectionEStats' GetPerTcp6ConnectionEStats iphlpapi 0
imp 'GetPerTcpConnectionEStats' GetPerTcpConnectionEStats iphlpapi 0
imp 'GetRTTAndHopCount' GetRTTAndHopCount iphlpapi 0
imp 'GetTcp6Table' GetTcp6Table iphlpapi 0
imp 'GetTcp6Table2' GetTcp6Table2 iphlpapi 0
imp 'GetTcpStatistics' GetTcpStatistics iphlpapi 0
imp 'GetTcpStatisticsEx' GetTcpStatisticsEx iphlpapi 0
imp 'GetTcpStatisticsEx2' GetTcpStatisticsEx2 iphlpapi 0
imp 'GetTcpTable' GetTcpTable iphlpapi 0 3
imp 'GetTcpTable2' GetTcpTable2 iphlpapi 0 3
imp 'GetUdp6Table' GetUdp6Table iphlpapi 0
imp 'GetUdpStatistics' GetUdpStatistics iphlpapi 0
imp 'GetUdpStatisticsEx' GetUdpStatisticsEx iphlpapi 0
imp 'GetUdpStatisticsEx2' GetUdpStatisticsEx2 iphlpapi 0
imp 'GetUdpTable' GetUdpTable iphlpapi 0
imp 'GetUniDirectionalAdapterInfo' GetUniDirectionalAdapterInfo iphlpapi 0
imp 'IpReleaseAddress' IpReleaseAddress iphlpapi 0
imp 'IpRenewAddress' IpRenewAddress iphlpapi 0
imp 'LookupPersistentTcpPortReservation' LookupPersistentTcpPortReservation iphlpapi 0
imp 'LookupPersistentUdpPortReservation' LookupPersistentUdpPortReservation iphlpapi 0
imp 'NhpAllocateAndGetInterfaceInfoFromStack' NhpAllocateAndGetInterfaceInfoFromStack iphlpapi 0
imp 'NotifyAddrChange' NotifyAddrChange iphlpapi 0
imp 'NotifyRouteChange' NotifyRouteChange iphlpapi 0
imp 'ParseNetworkString' ParseNetworkString iphlpapi 0
imp 'RegisterInterfaceTimestampConfigChange' RegisterInterfaceTimestampConfigChange iphlpapi 0
imp 'ResolveNeighbor' ResolveNeighbor iphlpapi 0
imp 'RestoreMediaSense' RestoreMediaSense iphlpapi 0
imp 'SendARP' SendARP iphlpapi 0
imp 'SetIfEntry' SetIfEntry iphlpapi 0
imp 'SetIpForwardEntry' SetIpForwardEntry iphlpapi 0
imp 'SetIpNetEntry' SetIpNetEntry iphlpapi 0
imp 'SetIpStatistics' SetIpStatistics iphlpapi 0
imp 'SetIpStatisticsEx' SetIpStatisticsEx iphlpapi 0
imp 'SetIpTTL' SetIpTTL iphlpapi 0
imp 'SetPerTcp6ConnectionEStats' SetPerTcp6ConnectionEStats iphlpapi 0
imp 'SetPerTcpConnectionEStats' SetPerTcpConnectionEStats iphlpapi 0
imp 'SetTcpEntry' SetTcpEntry iphlpapi 0
imp 'UnenableRouter' UnenableRouter iphlpapi 0
imp 'UnregisterInterfaceTimestampConfigChange' UnregisterInterfaceTimestampConfigChange iphlpapi 0

View file

@ -0,0 +1,291 @@
#ifndef COSMOPOLITAN_LIBC_NT_STRUCT_IP_ADAPTER_ADDRESSES_H_
#define COSMOPOLITAN_LIBC_NT_STRUCT_IP_ADAPTER_ADDRESSES_H_
#include "libc/nt/winsock.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
/* Constants ----------------------------------------------------------- */
#define kNtMaxAdapterAddressLength 8
#define kNtMaxDnsSuffixStringLength 256
#define kNtMaxDhcpv6DuidLength 130
/* Values for the 'Flags' parameter of GetAdaptersAddresses */
#define kNtGaaFlagSkipUnicast 0x0001
#define kNtGaaFlagSkipAnycast 0x0002
#define kNtGaaFlagSkipMulticast 0x0004
#define kNtGaaFlagSkipDnsServer 0x0008
#define kNtGaaFlagIncludePrefix 0x0010
#define kNtGaaFlagSkipFriendlyName 0x0020
#define kNtGaaFlagIncludeWinsInfo 0x0040
#define kNtGaaFlagIncludeGateways 0x0080
#define kNtGaaFlagIncludeAllInterfaces 0x0100
#define kNtGaaFlagIncludeAllCompartments 0x0200
#define kNtGaaFlagIncludeTunnelBindingorder 0x0400
#define kNtGaaFlagSkipDnsInfo 0x0800
/* Values for the IfType parameter
* See: https://docs.microsoft.com/en-us/windows/win32/api/iptypes/ns-iptypes-ip_adapter_addresses_lh
*/
#define kNtIfTypeOther 1
#define kNtIfTypeEthernetCsmacd 6
#define kNtIfTypeIso88025Tokenring 9
#define kNtIfTypePpp 23
#define kNtIfTypeSoftwareLoopback 24
#define kNtIfTypeAtm 37
#define kNtIfTypeIeee80211 71 /* wifi */
#define kNtIfTypeTunnel 131
#define kNtIfTypeIeee1394 144 /* firewire */
/* Enums --------------------------------------------------------------- */
typedef enum {
kNtIpPrefixOriginOther,
kNtIpPrefixOriginManual,
kNtIpPrefixOriginWellKnown,
kNtIpPrefixOriginDhcp,
kNtIpPrefixOriginRouterAdvertisement,
kNtIpPrefixOriginUnchanged
} NtPrefixOrigin;
typedef enum {
kNtNlsoOther,
kNtNlsoManual,
kNtNlsoWellKnown,
kNtNlsoDhcp,
kNtNlsoLinkLayerAddress,
kNtNlsoRandom,
kNtIpSuffixOriginOther,
kNtIpSuffixOriginManual,
kNtIpSuffixOriginWellKnown,
kNtIpSuffixOriginDhcp,
kNtIpSuffixOriginLinkLayerAddress,
kNtIpSuffixOriginRandom,
kNtIpSuffixOriginUnchanged
} NtSuffixOrigin;
typedef enum {
kNtNldsInvalid,
kNtNldsTentative,
kNtNldsDuplicate,
kNtNldsDeprecated,
kNtNldsPreferred,
kNtIpDadStateInvalid,
kNtIpDadStateTentative,
kNtIpDadStateDuplicate,
kNtIpDadStateDeprecated,
kNtIpDadStatePreferred
} NtDadState;
typedef enum {
kNtIfOperStatusUp = 1,
kNtIfOperStatusDown,
kNtIfOperStatusTesting,
kNtIfOperStatusUnknown,
kNtIfOperStatusDormant,
kNtIfOperStatusNotPresent,
kNtIfOperStatusLowerLayerDown
} NtIfOperStatus;
typedef enum {
kNtNetIfConnectionDedicated = 1,
kNtNetIfConnectionPassive = 2,
kNtNetIfConnectionDemand = 3,
kNtNetIfConnectionMaximum = 4
} NtNetIfConnectionType;
typedef enum {
kNtTunnelTypeNone = 0,
kNtTunnelTypeOther = 1,
kNtTunnelTypeDirect = 2,
kNtTunnelType6to4 = 11,
kNtTunnelTypeIsatap = 13,
kNtTunnelTypeTeredo = 14,
kNtTunnelTypeIphttps = 15
} NtTunnelType;
/* Inner Types --------------------------------------------------------- */
typedef struct _NtIpAdapterUnicastAddress {
union {
uint64_t Alignment;
struct {
uint32_t Length;
uint32_t Flags;
};
};
struct _NtIpAdapterUnicastAddress * Next;
struct NtSocketAddress Address;
NtPrefixOrigin PrefixOrigin;
NtSuffixOrigin SuffixOrigin;
NtDadState DadState;
uint32_t ValidLifetime;
uint32_t PreferredLifetime;
uint32_t LeaseLifetime;
uint8_t OnLinkPrefixLength;
} NtIpAdapterUnicastAddress;
typedef struct NtIpAdapterAnycastAddress {
union {
uint64_t Alignment;
struct {
uint32_t Length;
uint32_t Flags;
};
};
struct _NtIpAdapterAnycastAddress *Next;
struct NtSocketAddress Address;
} NtIpAdapterAnycastAddress;
typedef struct NtIpAdapterMulticastAddress {
union {
uint64_t Alignment;
struct {
uint32_t Length;
uint32_t Flags;
};
};
struct _NtIpAdapterMulticastAddress *Next;
struct NtSocketAddress Address;
} NtIpAdapterMulticastAddress;
typedef struct _NtIpAdapterDnsServerAddress {
union {
uint64_t Alignment;
struct {
uint32_t Length;
uint32_t Reserved;
};
};
struct _NtIpAdapterDnsServerAddress *Next;
struct NtSocketAddress Address;
} NtIpAdapterDnsServerAddress;
typedef struct _NtIpAdapterPrefix {
union {
uint64_t Alignment;
struct {
uint32_t Length;
uint32_t Flags;
};
};
struct _NtIpAdapterPrefix *Next;
struct NtSocketAddress Address;
uint32_t PrefixLength;
} NtIpAdapterPrefix;
typedef struct _NtIpAdapterWinsServerAddress {
union {
uint64_t Alignment;
struct {
uint32_t Length;
uint32_t Reserved;
};
};
struct _NtIpAdapterWinsServerAddress *Next;
struct NtSocketAddress Address;
} NtIpAdapterWinsServerAddress;
typedef struct _NtIpAdapterGatewayAddress {
union {
uint64_t Alignment;
struct {
uint32_t Length;
uint32_t Reserved;
};
};
struct _NtIpAdapterGatewayAddress *Next;
struct NtSocketAddress Address;
} NtIpAdapterGatewayAddress;
typedef struct _NtGUID {
uint32_t Data1;
uint16_t Data2;
uint16_t Data3;
uint8_t Data4[8];
} NtGUID;
typedef union _NtNetLUID
{
uint64_t Value;
struct
{
uint64_t Reserved:24;
uint64_t NetLuidIndex:24;
uint64_t IfType:16;
}Info;
} NtNetLUID;
typedef struct _NtIpAdapterDnsSuffix {
struct _NtIpAdapterDnsSuffix *Next;
uint16_t String[kNtMaxDnsSuffixStringLength];
} NtIpAdapterDnsSuffix;
/* Top level ----------------------------------------------------------- */
typedef struct _NtIpAdapterAddresses {
union {
uint64_t Alignment;
struct {
uint32_t Length;
uint32_t IfIndex;
};
};
struct _NtIpAdapterAddresses * Next;
char * AdapterName;
NtIpAdapterUnicastAddress * FirstUnicastAddress;
NtIpAdapterAnycastAddress * FirstAnycastAddress;
NtIpAdapterMulticastAddress * FirstMulticastAddress;
NtIpAdapterDnsServerAddress * FirstDnsServerAddress;
uint16_t * DnsSuffix;
uint16_t * Description;
uint16_t * FriendlyName;
uint8_t PhysicalAddress[kNtMaxAdapterAddressLength];
uint32_t PhysicalAddressLength;
union {
uint32_t Flags;
struct {
uint32_t DdnsEnabled : 1;
uint32_t RegisterAdapterSuffix : 1;
uint32_t Dhcpv4Enabled : 1;
uint32_t ReceiveOnly : 1;
uint32_t NoMulticast : 1;
uint32_t Ipv6OtherStatefulConfig : 1;
uint32_t NetbiosOverTcpipEnabled : 1;
uint32_t Ipv4Enabled : 1;
uint32_t Ipv6Enabled : 1;
uint32_t Ipv6ManagedAddressConfigurationSupported : 1;
};
};
uint32_t Mtu;
uint32_t IfType;
NtIfOperStatus OperStatus;
uint32_t Ipv6IfIndex;
uint32_t ZoneIndices[16];
NtIpAdapterPrefix * FirstPrefix;
uint64_t TransmitLinkSpeed;
uint64_t ReceiveLinkSpeed;
NtIpAdapterWinsServerAddress * FirstWinsServerAddress;
NtIpAdapterGatewayAddress * FirstGatewayAddress;
uint32_t Ipv4Metric;
uint32_t Ipv6Metric;
NtNetLUID Luid;
struct NtSocketAddress Dhcpv4Server;
uint32_t CompartmentId;
NtGUID NetworkGuid;
NtNetIfConnectionType ConnectionType;
NtTunnelType TunnelType;
struct NtSocketAddress Dhcpv6Server;
uint8_t Dhcpv6ClientDuid[kNtMaxDhcpv6DuidLength];
uint32_t Dhcpv6ClientDuidLength;
uint32_t Dhcpv6Iaid;
NtIpAdapterDnsSuffix * FirstDnsSuffix;
} NtIpAdapterAddresses;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NT_STRUCT_IP_ADAPTER_ADDRESSES_H_ */

View file

@ -26,9 +26,11 @@
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/sock.h"
/* ioctl(SIOCGIFCONFIG) uses GetAdaptersAddresses as weak ref */
/* ioctl(SIOCGIFCONFIG) for Windows need to access the following functions through
* weak reference. This ensure those symbols are not stripped during final link
*/
STATIC_YOINK("GetAdaptersAddresses");
STATIC_YOINK("WideCharToMultiByte");
STATIC_YOINK("tprecode16to8");
textwindows int sys_socket_nt(int family, int type, int protocol) {
int64_t h;