diff --git a/libc/calls/calls.mk b/libc/calls/calls.mk index 0e31c8da9..003d04fef 100644 --- a/libc/calls/calls.mk +++ b/libc/calls/calls.mk @@ -83,6 +83,12 @@ o/$(MODE)/libc/calls/mkntenvblock.o: \ OVERRIDE_CPPFLAGS += \ -DSTACK_FRAME_UNLIMITED +o/$(MODE)/libc/calls/ioctl-siocgifconf.o \ +o/$(MODE)/libc/calls/ioctl-siocgifconf-nt.o: \ + OVERRIDE_COPTS += \ + -ffunction-sections \ + -fdata-sections + LIBC_CALLS_LIBS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x))) LIBC_CALLS_SRCS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_SRCS)) LIBC_CALLS_HDRS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_HDRS)) diff --git a/libc/calls/ioctl-default.c b/libc/calls/ioctl_default.c similarity index 100% rename from libc/calls/ioctl-default.c rename to libc/calls/ioctl_default.c diff --git a/libc/calls/ioctl-siocgifconf-nt.c b/libc/calls/ioctl_siocgifconf-nt.c similarity index 67% rename from libc/calls/ioctl-siocgifconf-nt.c rename to libc/calls/ioctl_siocgifconf-nt.c index 76101b94c..3a1e4cede 100644 --- a/libc/calls/ioctl-siocgifconf-nt.c +++ b/libc/calls/ioctl_siocgifconf-nt.c @@ -16,45 +16,45 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" +#include "libc/bits/weaken.h" #include "libc/calls/calls.h" #include "libc/calls/internal.h" -#include "libc/sysv/consts/o.h" -#include "libc/sysv/consts/af.h" -#include "libc/sock/sock.h" -#include "libc/sock/internal.h" -#include "libc/sysv/errfuns.h" -#include "libc/sysv/consts/iff.h" -#include "libc/nt/winsock.h" #include "libc/nt/errors.h" #include "libc/nt/iphlpapi.h" +#include "libc/nt/runtime.h" #include "libc/nt/struct/ipadapteraddresses.h" -#include "libc/bits/weaken.h" +#include "libc/nt/winsock.h" +#include "libc/sock/internal.h" +#include "libc/sock/sock.h" #include "libc/str/str.h" -#include "libc/assert.h" -//#include "libc/nt/windows.h" /* Needed for WideCharToMultiByte */ +#include "libc/sysv/consts/af.h" +#include "libc/sysv/consts/iff.h" +#include "libc/sysv/consts/o.h" +#include "libc/sysv/errfuns.h" /* 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(NtIpAdapterAddresses *aa); +#define MAX_UNICAST_ADDR 32 +#define MAX_NAME_CLASH ((int)('z' - 'a')) /* Allow a..z */ struct HostAdapterInfoNode { - struct HostAdapterInfoNode * next; - char name[IFNAMSIZ]; /* Obtained from FriendlyName */ + struct HostAdapterInfoNode *next; + char name[IFNAMSIZ]; /* Obtained from FriendlyName */ struct sockaddr unicast; struct sockaddr netmask; struct sockaddr broadcast; short flags; -} *__hostInfo; +} * __hostInfo; /* Frees all the nodes of the _hostInfo */ -static void freeHostInfo() { +static void freeHostInfo(void) { struct HostAdapterInfoNode *next, *node = __hostInfo; - while(node) { - next = node->next; - weaken(free)(node); - node = next; + if (weaken(free)) { + while (node) { + next = node->next; + weaken(free)(node); + node = next; + } } __hostInfo = NULL; } @@ -65,14 +65,12 @@ static void freeHostInfo() { */ static struct HostAdapterInfoNode *findAdapterByName(const char *name) { struct HostAdapterInfoNode *node = __hostInfo; - while(node) { + while (node) { if (!strncmp(name, node->name, IFNAMSIZ)) { - /* Found */ return node; } - node=node->next; + node = node->next; } - /* Not found */ return NULL; } @@ -86,19 +84,22 @@ static struct HostAdapterInfoNode *findAdapterByName(const char *name) { */ 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 */ + const char *baseName, /* Max length = IFNAMSIZ-1 */ + const struct NtIpAdapterAddresses + *aa, /* Top level adapter object being processed */ + struct NtIpAdapterUnicastAddress * + *ptrUA, /* Ptr to ptr to unicast address list node */ + struct NtIpAdapterPrefix * + *ptrAP, /* Ptr to ptr to Adapter prefix list node */ + int count) { /* count is used to create a unique name in case of alias */ struct HostAdapterInfoNode *temp; struct HostAdapterInfoNode *node; - struct sockaddr_in tempAddr; + uint32_t ip, netmask, broadcast; + struct sockaddr_in *a; int attemptNum; - node = weaken(calloc)(1, sizeof(*node)); - if (!node) { + if (!weaken(calloc) || !(node = weaken(calloc)(1, sizeof(*node)))) { errno = ENOMEM; return NULL; } @@ -109,37 +110,38 @@ struct HostAdapterInfoNode *appendHostInfo( if (count > 0 || ((*ptrUA)->Next != NULL)) { /* Yes, compose it using : */ size_t nameLen = strlen(node->name); - if (nameLen+2 > IFNAMSIZ-2) { + 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 - 2] = ':'; + node->name[nameLen - 1] = '0' + count; node->name[nameLen] = '\0'; } /* Is there a name clash with other interfaces? */ - for (attemptNum=0; attemptNum < MAX_NAME_CLASH; ++attemptNum) { + 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 + /* 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); node->name[pos] = 'a' + attemptNum; - node->name[pos+1] = '\0'; + node->name[pos + 1] = '\0'; /* Try again */ } } + if (attemptNum == MAX_NAME_CLASH) { /* Cannot resolve the conflict */ - weaken(free)(node); + if (weaken(free)) { + weaken(free)(node); + } errno = EEXIST; return NULL; } @@ -161,28 +163,47 @@ struct HostAdapterInfoNode *appendHostInfo( 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->Flags & kNtIpAdapterNoMulticast)) flags |= IFF_MULTICAST; if (aa->IfType == kNtIfTypeSoftwareLoopback) flags |= IFF_LOOPBACK; - if (aa->FirstPrefix != NULL) flags |= IFF_BROADCAST; + if (aa->FirstPrefix) flags |= IFF_BROADCAST; node->flags = flags; } else { /* Copy from previous node */ node->flags = parentInfoNode->flags; } + ip = ntohl( + ((struct sockaddr_in *)(*ptrUA)->Address.lpSockaddr)->sin_addr.s_addr); + netmask = (uint32_t)-1 << (32 - (*ptrUA)->OnLinkPrefixLength); + broadcast = (ip & netmask) | (~netmask & -1); + + a = (struct sockaddr_in *)&node->netmask; + a->sin_family = AF_INET; + a->sin_addr.s_addr = htonl(netmask); + + a = (struct sockaddr_in *)&node->broadcast; + a->sin_family = AF_INET; + a->sin_addr.s_addr = htonl(broadcast); + /* 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. + * + * 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. + * -Source: MSDN on IP_ADAPTER_ADDRESSES_LH * * For example, interface "Ethernet", with 2 unicast addresses: - * - 192.168.1.84 + * + * - 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 @@ -195,20 +216,16 @@ struct HostAdapterInfoNode *appendHostInfo( * #8: 255.255.255.255/32 <- Broadcast */ - /* 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)); + if (ptrAP && *ptrAP) { + *ptrAP = (*ptrAP)->Next; /* skip net ip */ + if (*ptrAP) { + *ptrAP = (*ptrAP)->Next; /* skip host ip */ + if (*ptrAP) { + node->broadcast = *((*ptrAP)->Address.lpSockaddr); + } + } + } - *ptrAP = (*ptrAP)->Next; - *ptrAP = (*ptrAP)->Next; /* Skip over Host IP */ - - /* Broadcast */ - node->broadcast = *((*ptrAP)->Address.lpSockaddr); - *ptrAP = (*ptrAP)->Next; - - /* Move pointer to Unicast Address record */ *ptrUA = (*ptrUA)->Next; /* Append this node to the last node (if any) */ @@ -221,10 +238,10 @@ struct HostAdapterInfoNode *appendHostInfo( } /* Returns -1 in case of failure */ -static int createHostInfo(NtIpAdapterAddresses *firstAdapter) { - NtIpAdapterAddresses *aa; - NtIpAdapterUnicastAddress *ua; - NtIpAdapterPrefix *ap; +static int createHostInfo(struct NtIpAdapterAddresses *firstAdapter) { + struct NtIpAdapterAddresses *aa; + struct NtIpAdapterUnicastAddress *ua; + struct NtIpAdapterPrefix *ap; struct HostAdapterInfoNode *node = NULL; char baseName[IFNAMSIZ]; char name[IFNAMSIZ]; @@ -232,34 +249,31 @@ static int createHostInfo(NtIpAdapterAddresses *firstAdapter) { /* __hostInfo must be empty */ assert(__hostInfo == NULL); - assert(weaken(tprecode16to8)); 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 || + /* 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'; + tprecode16to8(baseName, IFNAMSIZ - 1, aa->FriendlyName); + baseName[IFNAMSIZ - 2] = '\0'; /* Replace any space with a '_' */ - for (i = 0; i < IFNAMSIZ-2; ++i) { + for (i = 0; i < IFNAMSIZ - 2; ++i) { if (baseName[i] == ' ') baseName[i] = '_'; if (!baseName[i]) break; } - for (count = 0, ua = aa->FirstUnicastAddress, ap = aa->FirstPrefix; - (ua != NULL) && (count < MAX_UNICAST_ADDR); - ++count) { + 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 (!node) goto err; if (!__hostInfo) __hostInfo = node; } - /* Note: do we need to process the remaining adapter prefix? + /* 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 @@ -268,55 +282,57 @@ static int createHostInfo(NtIpAdapterAddresses *firstAdapter) { return 0; err: - freeHostInfo(__hostInfo); + freeHostInfo(); return -1; } static int readAdapterAddresses(void) { uint32_t size, rc; - NtIpAdapterAddresses * aa = NULL; - - assert(weaken(GetAdaptersAddresses)); + struct NtIpAdapterAddresses *aa = NULL; /* Calculate the required data size - * Note: alternatively you can use AF_UNSPEC to also return IPv6 interfaces + * 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); + rc = GetAdaptersAddresses(AF_INET, + kNtGaaFlagSkipAnycast | kNtGaaFlagSkipMulticast | + kNtGaaFlagSkipDnsServer | + kNtGaaFlagIncludePrefix, + NULL, /* Reserved */ + NULL, /* Ptr */ + &size); if (rc != kNtErrorBufferOverflow) { ebadf(); goto err; } - aa = (NtIpAdapterAddresses *)weaken(malloc)(size); - if (!aa) { + if (!weaken(malloc) || + !(aa = (struct NtIpAdapterAddresses *)weaken(malloc)(size))) { 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); + rc = GetAdaptersAddresses(AF_INET, + kNtGaaFlagSkipAnycast | kNtGaaFlagSkipMulticast | + kNtGaaFlagSkipDnsServer | + kNtGaaFlagIncludePrefix, + // kNtGaaFlagIncludePrefix, + NULL, aa, &size); if (rc != kNtErrorSuccess) { - efault(); + errno = GetLastError(); goto err; } if (createHostInfo(aa) == -1) { goto err; } - weaken(free)(aa); + if (weaken(free)) { + weaken(free)(aa); + } return 0; err: - if (aa) { + if (weaken(free)) { weaken(free)(aa); } freeHostInfo(); @@ -324,7 +340,7 @@ err: } textwindows int ioctl_siocgifconf_nt(int fd, struct ifconf *ifc) { - NtIpAdapterAddresses *aa; + struct NtIpAdapterAddresses *aa; struct HostAdapterInfoNode *node; struct ifreq *ptr; @@ -337,8 +353,8 @@ textwindows int ioctl_siocgifconf_nt(int fd, struct ifconf *ifc) { } for (ptr = ifc->ifc_req, node = __hostInfo; - (((char *)(ptr+1) - ifc->ifc_buf) < ifc->ifc_len) && node; - ptr++, node = node->next) { + (((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)); } @@ -347,14 +363,13 @@ textwindows int ioctl_siocgifconf_nt(int fd, struct ifconf *ifc) { return 0; } -/* Performs the SIOCGIFADDR operation */ +/** + * Returns unicast addresses. + */ int ioctl_siocgifaddr_nt(int fd, struct ifreq *ifr) { struct HostAdapterInfoNode *node; - node = findAdapterByName(ifr->ifr_name); - if (!node) { - return ebadf(); - } + if (!node) return ebadf(); memcpy(&ifr->ifr_addr, &node->unicast, sizeof(struct sockaddr)); return 0; } @@ -362,37 +377,28 @@ int ioctl_siocgifaddr_nt(int fd, struct ifreq *ifr) { /* Performs the SIOCGIFFLAGS operation */ int ioctl_siocgifflags_nt(int fd, struct ifreq *ifr) { struct HostAdapterInfoNode *node; - node = findAdapterByName(ifr->ifr_name); - if (!node) { - return ebadf(); - } + if (!node) return ebadf(); ifr->ifr_flags = node->flags; return 0; } - /* Performs the SIOCGIFNETMASK operation */ int ioctl_siocgifnetmask_nt(int fd, struct ifreq *ifr) { struct HostAdapterInfoNode *node; - node = findAdapterByName(ifr->ifr_name); - if (!node) { - return ebadf(); - } + if (!node) return ebadf(); memcpy(&ifr->ifr_netmask, &node->netmask, sizeof(struct sockaddr)); return 0; } -/* Performs the SIOCGIFBRDADDR operation */ +/** + * Returns broadcast address. + */ int ioctl_siocgifbrdaddr_nt(int fd, struct ifreq *ifr) { struct HostAdapterInfoNode *node; - node = findAdapterByName(ifr->ifr_name); - if (!node) { - return ebadf(); - } + if (!node) return ebadf(); memcpy(&ifr->ifr_broadaddr, &node->broadcast, sizeof(struct sockaddr)); return 0; } - diff --git a/libc/calls/ioctl-siocgifconf.c b/libc/calls/ioctl_siocgifconf.c similarity index 70% rename from libc/calls/ioctl-siocgifconf.c rename to libc/calls/ioctl_siocgifconf.c index 5bcc144e6..427a4dd74 100644 --- a/libc/calls/ioctl-siocgifconf.c +++ b/libc/calls/ioctl_siocgifconf.c @@ -16,12 +16,15 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/assert.h" #include "libc/bits/weaken.h" -#include "libc/sysv/errfuns.h" #include "libc/calls/internal.h" -#include "libc/sock/sock.h" #include "libc/sock/internal.h" +#include "libc/sock/sock.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/af.h" #include "libc/sysv/consts/sio.h" +#include "libc/sysv/errfuns.h" /* SIOCGIFCONF: * Takes an struct ifconf object of a given size @@ -29,7 +32,7 @@ * - ifc_len: set it to the number of valid ifreq structures representing * the interfaces * - ifc_ifcu.ifcu_req: sets the name of the interface for each interface - * The ifc_len is an input/output parameter: set it to the total size of + * The ifc_len is an input/output parameter: set it to the total size of * the ifcu_buf (ifcu_req) buffer on input. */ int ioctl_default(int, uint64_t, void *) hidden; @@ -40,79 +43,59 @@ 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()) { - /* BSD uses a slightly different memory structure where: - * - sizeof(struct ifreq) is 32 bytes instead of 40 bytes - * - ifc.ifc_len is uint32_t instead of uint64_t - * - struct ifconf is #pragma pack(4) (instead of the default pack(8)) - */ - int i; - char *buf; /* Temporary buffer to store ifreq */ - char *pBsdReq; /* Scan through buf records */ - char *pBsdEnd; /* End of the ifreq */ - - struct ifconf_bsd ifc_bsd; - struct ifreq_bsd *bsdReq; - struct ifreq *req; - size_t numReq = ifc->ifc_len / sizeof(struct ifreq); - - if (!weaken(malloc)) { - return enomem(); - } - ifc_bsd.ifc_len = numReq * sizeof(struct ifreq_bsd); - buf = weaken(malloc)(ifc_bsd.ifc_len); - if (!buf) { - return enomem(); - } - ifc_bsd.ifc_buf = buf; - - if ((i = sys_ioctl(fd, SIOCGIFCONF, &ifc_bsd)) < 0) { - weaken(free)(buf); - return -1; - } - - /* On BSD the size of the struct ifreq is different than Linux. - * On Linux is fixed (40 bytes), but on BSD the struct sockaddr + /* + * We're 100% compatible with Linux. + * BSD ABIs mainly differ by having sockaddr::sa_len + * XNU uses a 32-bit length in a struct that's packed! + */ + int i, rc, fam; + char *b, *p, *e; + char ifcBsd[16]; + struct ifreq *req; + struct ifreq *end; + uint32_t bufLen, ip; + size_t numReq, bufMax; + if (IsLinux()) return sys_ioctl(fd, SIOCGIFCONF, ifc); + if (!weaken(malloc)) return enomem(); + bufMax = 15000; /* conservative guesstimate */ + if (!(b = weaken(malloc)(bufMax))) return enomem(); + memcpy(ifcBsd, &bufMax, 8); /* ifc_len */ + memcpy(ifcBsd + (IsXnu() ? 4 : 8), &b, 8); /* ifc_buf */ + if ((rc = sys_ioctl(fd, SIOCGIFCONF, &ifcBsd)) != -1) { + /* + * On XNU the size of the struct ifreq is different than Linux. + * On Linux is fixed (40 bytes), but on XNU the struct sockaddr * has variable length, making the whole struct ifreq a variable * sized record. */ - for (pBsdReq = buf, pBsdEnd = buf + ifc_bsd.ifc_len, req = ifc->ifc_req; - pBsdReq < pBsdEnd; - ++req) { - bsdReq = (struct ifreq_bsd *)pBsdReq; - memcpy(req->ifr_name, bsdReq->ifr_name, IFNAMSIZ); - memcpy(&req->ifr_addr, &bsdReq->ifr_addr, sizeof(struct sockaddr_bsd)); - sockaddr2linux(&req->ifr_addr); - - pBsdReq += IFNAMSIZ + bsdReq->ifr_addr.sa_len; + memcpy(&bufLen, b, 4); + req = ifc->ifc_req; + end = req + ifc->ifc_len / sizeof(*req); + for (p = b, e = p + MIN(bufMax, READ32LE(ifcBsd)); p + 16 + 16 <= e; + p += IsBsd() ? 16 + MAX(16, p[16] & 255) : 40) { + fam = p[IsBsd() ? 17 : 16] & 255; + if (fam != AF_INET) continue; + ip = READ32BE(p + 20); + memset(req, 0, sizeof(*req)); + memcpy(req->ifr_name, p, 16); + memcpy(&req->ifr_addr, p + 16, 16); + req->ifr_addr.sa_family = fam; + ((struct sockaddr_in *)&req->ifr_addr)->sin_addr.s_addr = htonl(ip); + ++req; } - - /* Adjust len */ - ifc->ifc_len = (size_t)((char *)req - ifc->ifc_buf); - weaken(free)(buf); - return 0; - - } else { - /* 100% compatible with Linux */ - return sys_ioctl(fd, SIOCGIFCONF, ifc); + ifc->ifc_len = (char *)req - ifc->ifc_buf; /* Adjust len */ } + if (weaken(free)) weaken(free)(b); + return rc; } /* Used for all the ioctl that returns sockaddr structure that - * requires adjustment between Linux and BSD + * requires adjustment between Linux and XNU */ static int ioctl_siocgifaddr_sysv(int fd, uint64_t op, struct ifreq *ifr) { - int i; - - if (IsBsd()) { - sockaddr2bsd(&ifr->ifr_addr); - } - if ((i = sys_ioctl(fd, op, ifr)) < 0) { - return -1; - } - if (IsBsd()) { - sockaddr2linux(&ifr->ifr_addr); - } + if (IsBsd()) sockaddr2bsd(&ifr->ifr_addr); + if (sys_ioctl(fd, op, ifr) == -1) return -1; + if (IsBsd()) sockaddr2linux(&ifr->ifr_addr); return 0; } @@ -163,14 +146,13 @@ int ioctl_siocgifdstaddr(int fd, void *ifr) { * GetAdaptersAddresses function * return ioctl_siocgifbrdaddr_nt(fd, ifc); - */ } } int ioctl_siocgifflags(int fd, void *ifr) { if (!IsWindows()) { - /* Both BSD and Linux are for once compatible here... */ + /* Both XNU and Linux are for once compatible here... */ return ioctl_default(fd, SIOCGIFFLAGS, ifr); } else { return ioctl_siocgifflags_nt(fd, (struct ifreq *)ifr); diff --git a/libc/calls/ioctl-tcgets-nt.c b/libc/calls/ioctl_tcgets-nt.c similarity index 100% rename from libc/calls/ioctl-tcgets-nt.c rename to libc/calls/ioctl_tcgets-nt.c diff --git a/libc/calls/ioctl-tcgets.c b/libc/calls/ioctl_tcgets.c similarity index 100% rename from libc/calls/ioctl-tcgets.c rename to libc/calls/ioctl_tcgets.c diff --git a/libc/calls/ioctl-tcsets-nt.c b/libc/calls/ioctl_tcsets-nt.c similarity index 100% rename from libc/calls/ioctl-tcsets-nt.c rename to libc/calls/ioctl_tcsets-nt.c diff --git a/libc/calls/ioctl-tcsets.c b/libc/calls/ioctl_tcsets.c similarity index 100% rename from libc/calls/ioctl-tcsets.c rename to libc/calls/ioctl_tcsets.c diff --git a/libc/calls/ioctl-tiocgwinsz-nt.c b/libc/calls/ioctl_tiocgwinsz-nt.c similarity index 100% rename from libc/calls/ioctl-tiocgwinsz-nt.c rename to libc/calls/ioctl_tiocgwinsz-nt.c diff --git a/libc/calls/ioctl-tiocgwinsz.c b/libc/calls/ioctl_tiocgwinsz.c similarity index 100% rename from libc/calls/ioctl-tiocgwinsz.c rename to libc/calls/ioctl_tiocgwinsz.c diff --git a/libc/calls/ioctl-tiocswinsz-nt.c b/libc/calls/ioctl_tiocswinsz-nt.c similarity index 100% rename from libc/calls/ioctl-tiocswinsz-nt.c rename to libc/calls/ioctl_tiocswinsz-nt.c diff --git a/libc/calls/ioctl-tiocswinsz.c b/libc/calls/ioctl_tiocswinsz.c similarity index 100% rename from libc/calls/ioctl-tiocswinsz.c rename to libc/calls/ioctl_tiocswinsz.c diff --git a/libc/calls/struct/sockaddr6.h b/libc/calls/struct/sockaddr6.h new file mode 100644 index 000000000..333135def --- /dev/null +++ b/libc/calls/struct/sockaddr6.h @@ -0,0 +1,22 @@ +#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_SOCKADDR6_H_ +#define COSMOPOLITAN_LIBC_CALLS_STRUCT_SOCKADDR6_H_ +#if !(__ASSEMBLER__ + __LINKER__ + 0) + +struct in6_addr { + union { + uint8_t s6_addr[16]; + uint16_t s6_addr16[8]; + uint32_t s6_addr32[4]; + }; +}; + +struct sockaddr_in6 { /* Linux+NT ABI */ + uint16_t sin6_family; + uint16_t sin6_port; + uint32_t sin6_flowinfo; + struct in6_addr sin6_addr; + uint32_t sin6_scope_id; /* rfc2553 */ +}; + +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_SOCKADDR6_H_ */ diff --git a/libc/dns/getnameinfo.c b/libc/dns/getnameinfo.c index ef8af10d8..3cbbc860c 100644 --- a/libc/dns/getnameinfo.c +++ b/libc/dns/getnameinfo.c @@ -33,6 +33,7 @@ #include "libc/dns/resolvconf.h" #include "libc/fmt/conv.h" #include "libc/fmt/fmt.h" +#include "libc/fmt/itoa.h" #include "libc/mem/mem.h" #include "libc/sock/sock.h" #include "libc/str/str.h" @@ -56,7 +57,7 @@ int getnameinfo(const struct sockaddr *addr, socklen_t addrlen, char *name, socklen_t namelen, char *service, socklen_t servicelen, int flags) { - char rdomain[1 + sizeof "255.255.255.255.in-addr.arpa"]; + char *p, rdomain[1 + sizeof "255.255.255.255.in-addr.arpa"]; char info[512]; int rc, port; uint8_t *ip; @@ -71,7 +72,11 @@ int getnameinfo(const struct sockaddr *addr, socklen_t addrlen, char *name, return EAI_FAMILY; ip = (uint8_t *)&(((struct sockaddr_in *)addr)->sin_addr); - sprintf(rdomain, "%d.%d.%d.%d.in-addr.arpa", ip[3], ip[2], ip[1], ip[0]); + p = rdomain; + p += int64toarray_radix10(ip[3], p), *p++ = '.'; + p += int64toarray_radix10(ip[2], p), *p++ = '.'; + p += int64toarray_radix10(ip[1], p), *p++ = '.'; + p += int64toarray_radix10(ip[0], p), stpcpy(p, ".in-addr.arpa"); info[0] = '\0'; if (name != NULL && namelen != 0) { if ((flags & NI_NUMERICHOST) && (flags & NI_NAMEREQD)) return EAI_NONAME; diff --git a/libc/dns/resolvehostsreverse.c b/libc/dns/resolvehostsreverse.c index c0eaf69e9..4fb77306e 100644 --- a/libc/dns/resolvehostsreverse.c +++ b/libc/dns/resolvehostsreverse.c @@ -44,8 +44,9 @@ int ResolveHostsReverse(const struct HostsTxt *ht, int af, const uint8_t *ip, if (af != AF_INET && af != AF_UNSPEC) return eafnosupport(); for (i = 0; i < ht->entries.i; ++i) { if (READ32LE(ip) == READ32LE(ht->entries.p[i].ip)) { - snprintf(buf, bufsize, "%s", ht->strings.p + ht->entries.p[i].name); - return 1; + if (memccpy(buf, ht->strings.p + ht->entries.p[i].name, '\0', bufsize)) { + return 1; + } } } return 0; diff --git a/libc/nt/iphlpapi.h b/libc/nt/iphlpapi.h index ce9c31a6d..4b55fe345 100644 --- a/libc/nt/iphlpapi.h +++ b/libc/nt/iphlpapi.h @@ -29,7 +29,7 @@ COSMOPOLITAN_C_START_ ╚────────────────────────────────────────────────────────────────────────────│*/ uint32_t GetAdaptersAddresses(uint32_t Family, uint32_t Flags, void *Reserved, - NtIpAdapterAddresses *AdapterAddresses, + struct NtIpAdapterAddresses *AdapterAddresses, uint32_t *SizePointer); COSMOPOLITAN_C_END_ diff --git a/libc/nt/struct/ipadapteraddresses.h b/libc/nt/struct/ipadapteraddresses.h index a8d169ac5..2c5cc448d 100644 --- a/libc/nt/struct/ipadapteraddresses.h +++ b/libc/nt/struct/ipadapteraddresses.h @@ -1,10 +1,10 @@ #ifndef COSMOPOLITAN_LIBC_NT_STRUCT_IP_ADAPTER_ADDRESSES_H_ #define COSMOPOLITAN_LIBC_NT_STRUCT_IP_ADAPTER_ADDRESSES_H_ +#include "libc/nt/struct/guid.h" #include "libc/nt/winsock.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ /* Constants ----------------------------------------------------------- */ + #define kNtMaxAdapterAddressLength 8 #define kNtMaxDnsSuffixStringLength 256 #define kNtMaxDhcpv6DuidLength 130 @@ -37,245 +37,167 @@ COSMOPOLITAN_C_START_ #define kNtIfTypeTunnel 131 #define kNtIfTypeIeee1394 144 /* firewire */ -/* Enums --------------------------------------------------------------- */ -typedef enum { - kNtIpPrefixOriginOther, - kNtIpPrefixOriginManual, - kNtIpPrefixOriginWellKnown, - kNtIpPrefixOriginDhcp, - kNtIpPrefixOriginRouterAdvertisement, - kNtIpPrefixOriginUnchanged -} NtPrefixOrigin; +#define kNtIpAdapterDdnsEnabled 0x0001 +#define kNtIpAdapterRegisterAdapterSuffix 0x0002 +#define kNtIpAdapterDhcpv4Enabled 0x0004 +#define kNtIpAdapterReceiveOnly 0x0008 +#define kNtIpAdapterNoMulticast 0x0010 +#define kNtIpAdapterIpv6OtherStatefulConfig 0x0020 +#define kNtIpAdapterNetbiosOverTcpipEnabled 0x0040 +#define kNtIpAdapterIpv4Enabled 0x0080 +#define kNtIpAdapterIpv6Enabled 0x0100 +#define kNtIpAdapterIpv6Managed 0x0200 -typedef enum { - kNtNlsoOther, - kNtNlsoManual, - kNtNlsoWellKnown, - kNtNlsoDhcp, - kNtNlsoLinkLayerAddress, - kNtNlsoRandom, - kNtIpSuffixOriginOther, - kNtIpSuffixOriginManual, - kNtIpSuffixOriginWellKnown, - kNtIpSuffixOriginDhcp, - kNtIpSuffixOriginLinkLayerAddress, - kNtIpSuffixOriginRandom, - kNtIpSuffixOriginUnchanged -} NtSuffixOrigin; +#define kNtIpPrefixOriginOther 0 +#define kNtIpPrefixOriginManual 1 +#define kNtIpPrefixOriginWellKnown 2 +#define kNtIpPrefixOriginDhcp 3 +#define kNtIpPrefixOriginRouterAdvertisement 4 +#define kNtIpPrefixOriginUnchanged 16 -typedef enum { - kNtNldsInvalid, - kNtNldsTentative, - kNtNldsDuplicate, - kNtNldsDeprecated, - kNtNldsPreferred, - kNtIpDadStateInvalid, - kNtIpDadStateTentative, - kNtIpDadStateDuplicate, - kNtIpDadStateDeprecated, - kNtIpDadStatePreferred -} NtDadState; +#define kNtIpSuffixOriginOther 0 +#define kNtIpSuffixOriginManual 1 +#define kNtIpSuffixOriginWellKnown 2 +#define kNtIpSuffixOriginDhcp 3 +#define kNtIpSuffixOriginLinkLayerAddress 4 +#define kNtIpSuffixOriginRandom 5 +#define kNtIpSuffixOriginUnchanged 16 -typedef enum { - kNtIfOperStatusUp = 1, - kNtIfOperStatusDown, - kNtIfOperStatusTesting, - kNtIfOperStatusUnknown, - kNtIfOperStatusDormant, - kNtIfOperStatusNotPresent, - kNtIfOperStatusLowerLayerDown -} NtIfOperStatus; +#define kNtIpDadStateInvalid 0 +#define kNtIpDadStateTentative 1 +#define kNtIpDadStateDuplicate 2 +#define kNtIpDadStateDeprecated 3 +#define kNtIpDadStatePreferred 4 -typedef enum { - kNtNetIfConnectionDedicated = 1, - kNtNetIfConnectionPassive = 2, - kNtNetIfConnectionDemand = 3, - kNtNetIfConnectionMaximum = 4 -} NtNetIfConnectionType; +#define kNtIfOperStatusUp 1 +#define kNtIfOperStatusDown 2 +#define kNtIfOperStatusTesting 3 +#define kNtIfOperStatusUnknown 4 +#define kNtIfOperStatusDormant 5 +#define kNtIfOperStatusNotPresent 6 +#define kNtIfOperStatusLowerLayerDown 7 -typedef enum { - kNtTunnelTypeNone = 0, - kNtTunnelTypeOther = 1, - kNtTunnelTypeDirect = 2, - kNtTunnelType6to4 = 11, - kNtTunnelTypeIsatap = 13, - kNtTunnelTypeTeredo = 14, - kNtTunnelTypeIphttps = 15 -} NtTunnelType; +#define kNtNetIfConnectionDedicated 1 +#define kNtNetIfConnectionPassive 2 +#define kNtNetIfConnectionDemand 3 +#define kNtNetIfConnectionMaximum 4 + +#define kNtTunnelTypeNone 0 +#define kNtTunnelTypeOther 1 +#define kNtTunnelTypeDirect 2 +#define kNtTunnelType6to4 11 +#define kNtTunnelTypeIsatap 13 +#define kNtTunnelTypeTeredo 14 +#define kNtTunnelTypeIphttps 15 + +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ /* Inner Types --------------------------------------------------------- */ -typedef struct _NtIpAdapterUnicastAddress { - union { - uint64_t Alignment; - struct { - uint32_t Length; - uint32_t Flags; - }; - }; - struct _NtIpAdapterUnicastAddress *Next; + +struct NtIpAdapterUnicastAddress { + uint32_t Length; + uint32_t Flags; + struct NtIpAdapterUnicastAddress *Next; struct NtSocketAddress Address; - NtPrefixOrigin PrefixOrigin; - NtSuffixOrigin SuffixOrigin; - NtDadState DadState; + uint32_t PrefixOrigin; /* kNtIpPrefixOrigin... */ + uint32_t SuffixOrigin; /* kNtIpSuffixOrigin... */ + uint32_t DadState; /* kNtIpDadState... */ 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 NtIpAdapterAnycastAddress { + 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 NtIpAdapterMulticastAddress { + 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 NtIpAdapterDnsServerAddress { + 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 NtIpAdapterPrefix { + 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 NtIpAdapterWinsServerAddress { + 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 NtIpAdapterGatewayAddress { + 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; +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; + +struct NtIpAdapterAddresses { + uint32_t Length; + uint32_t IfIndex; + struct NtIpAdapterAddresses *Next; char *AdapterName; - NtIpAdapterUnicastAddress *FirstUnicastAddress; - NtIpAdapterAnycastAddress *FirstAnycastAddress; - NtIpAdapterMulticastAddress *FirstMulticastAddress; - NtIpAdapterDnsServerAddress *FirstDnsServerAddress; + struct NtIpAdapterUnicastAddress *FirstUnicastAddress; + struct NtIpAdapterAnycastAddress *FirstAnycastAddress; + struct NtIpAdapterMulticastAddress *FirstMulticastAddress; + struct 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 Flags; /* kNtIpAdapter... */ uint32_t Mtu; - uint32_t IfType; - NtIfOperStatus OperStatus; + uint32_t IfType; /* kNtIfType... */ + uint32_t OperStatus; /* kNtIfOperStatus... */ uint32_t Ipv6IfIndex; uint32_t ZoneIndices[16]; - NtIpAdapterPrefix *FirstPrefix; + struct NtIpAdapterPrefix *FirstPrefix; uint64_t TransmitLinkSpeed; uint64_t ReceiveLinkSpeed; - NtIpAdapterWinsServerAddress *FirstWinsServerAddress; - NtIpAdapterGatewayAddress *FirstGatewayAddress; + struct NtIpAdapterWinsServerAddress *FirstWinsServerAddress; + struct NtIpAdapterGatewayAddress *FirstGatewayAddress; uint32_t Ipv4Metric; uint32_t Ipv6Metric; - NtNetLUID Luid; + uint64_t Luid; /* reserved(24bits),NetLuidIndex(24b),IfType(16b) */ struct NtSocketAddress Dhcpv4Server; uint32_t CompartmentId; - NtGUID NetworkGuid; - NtNetIfConnectionType ConnectionType; - NtTunnelType TunnelType; + struct NtGuid NetworkGuid; + uint32_t ConnectionType; /* kNtNetIfConnection... */ + uint32_t TunnelType; /* kNtTunnelType... */ struct NtSocketAddress Dhcpv6Server; uint8_t Dhcpv6ClientDuid[kNtMaxDhcpv6DuidLength]; uint32_t Dhcpv6ClientDuidLength; uint32_t Dhcpv6Iaid; - NtIpAdapterDnsSuffix *FirstDnsSuffix; -} NtIpAdapterAddresses; + struct NtIpAdapterDnsSuffix *FirstDnsSuffix; +}; COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/sock/gethostips.c b/libc/sock/gethostips.c index dd85e9a23..f0fa33a4a 100644 --- a/libc/sock/gethostips.c +++ b/libc/sock/gethostips.c @@ -59,8 +59,8 @@ static uint32_t *GetUnixIps(void) { static textwindows uint32_t *GetWindowsIps(void) { uint32_t i, z, n, rc, *a; - NtIpAdapterUnicastAddress *u; - NtIpAdapterAddresses *p, *ifaces; + struct NtIpAdapterUnicastAddress *u; + struct NtIpAdapterAddresses *p, *ifaces; i = 0; z = 15000; do { diff --git a/libc/sock/internal.h b/libc/sock/internal.h index 94ae89e19..49b3442de 100644 --- a/libc/sock/internal.h +++ b/libc/sock/internal.h @@ -53,45 +53,8 @@ struct sockaddr_un_bsd { char sun_path[108]; }; -/* ----------------------------------------------------------------------------------- - * ioctl SIOCGIFCONF & others: - * - * BSD has a different structure. All the ioctl will adjust to use - * the ifreq with the ifreq_bsd - */ -struct ifreq_bsd { - union { - char ifrn_name[IFNAMSIZ]; - } ifr_ifrn; - - union { - /* Right now we only list the structures used by the few ioctl that are - * supported by Cosmopolitan. Add your own definition here if you need - * a particular ioctl that requires polyfill for BSD - */ - struct sockaddr_bsd ifru_addr; - struct sockaddr_bsd ifru_netmask; - struct sockaddr_bsd ifru_dstaddr; - struct sockaddr_bsd ifru_broadaddr; - short ifru_flags; - char ifru_pad[16]; /* used as padding */ - } ifr_ifru; -}; - -#pragma pack(4) -struct ifconf_bsd { - uint32_t ifc_len; /* size of buffer */ - union { - char *ifcu_buf; - struct ifreq_bsd *ifcu_req; - } ifc_ifcu; -}; -#pragma pack() - - /* ------------------------------------------------------------------------------------*/ - struct SockFd { int family; int type; diff --git a/libc/sock/sock.h b/libc/sock/sock.h index c196ae08c..6eb96b9ca 100644 --- a/libc/sock/sock.h +++ b/libc/sock/sock.h @@ -102,11 +102,11 @@ struct ifconf { #define IFHWADDRLEN 6 #define IF_NAMESIZE 16 #define IFNAMSIZ IF_NAMESIZE + struct ifreq { union { char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */ } ifr_ifrn; - union { struct sockaddr ifru_addr; /* SIOCGIFADDR */ struct sockaddr ifru_dstaddr; /* SIOCGIFDSTADDR */ @@ -128,8 +128,6 @@ struct ifreq { #define _IOT_ifreq_short _IOT(_IOTS(char), IFNAMSIZ, _IOTS(short), 1, 0, 0) #define _IOT_ifreq_int _IOT(_IOTS(char), IFNAMSIZ, _IOTS(int), 1, 0, 0) -#define IFF_UP (1 << 0) - const char *inet_ntop(int, const void *, char *, uint32_t); int inet_aton(const char *, struct in_addr *); int inet_pton(int, const char *, void *); diff --git a/libc/sysv/consts.sh b/libc/sysv/consts.sh index 8ec8a2c76..c5723fd34 100755 --- a/libc/sysv/consts.sh +++ b/libc/sysv/consts.sh @@ -1497,14 +1497,18 @@ syscon modem TIOCMODG 0 0x40047403 0 0x4004746a 0x4004746a -1 # wut syscon modem TIOCMODS 0 0x80047404 0 0x8004746d 0x8004746d -1 # wut syscon modem TIOCMSDTRWAIT 0 0x8004745b 0x8004745b 0 0 -1 # wut -syscon iff IFF_BROADCAST 2 2 2 2 2 2 # consensus -syscon iff IFF_LOOPBACK 8 8 8 8 8 4 # unix consensus -syscon iff IFF_MULTICAST 0x1000 0x8000 0x8000 0x8000 0x8000 0x10 # bsd consensus -syscon iff IFF_ALLMULTI 0x0200 0x0200 0x0200 0x0200 0x0200 0 # unix consensus -syscon iff IFF_DEBUG 4 4 4 4 4 0 # unix consensus -syscon iff IFF_NOARP 0x80 0x80 0x80 0x80 0x80 0 # unix consensus -syscon iff IFF_POINTOPOINT 0x10 0x10 0x10 0x10 0x10 0 # unix consensus -syscon iff IFF_PROIFF 0x0100 0x0100 0x0100 0x0100 0x0100 0 # unix consensus +# ioctl(SIOCGIFFLAGS) Network Interface Flags +# +# group name GNU/Systemd XNU's Not UNIX! FreeBSD OpenBSD NetBSD The New Technology Commentary +syscon iff IFF_UP 1 1 1 1 1 1 # unix consensus +syscon iff IFF_BROADCAST 2 2 2 2 2 2 # valid broadcast address set; consensus +syscon iff IFF_DEBUG 4 4 4 4 4 4 # faked nt; consensus +syscon iff IFF_LOOPBACK 8 8 8 8 8 4 # is loopback device; consensus +syscon iff IFF_MULTICAST 0x1000 0x8000 0x8000 0x8000 0x8000 0x1000 # supports multicast; faked nt; bsd consensus +syscon iff IFF_ALLMULTI 0x0200 0x0200 0x0200 0x0200 0x0200 0x0200 # receive all multicast packets; faked nt; unix consensus +syscon iff IFF_NOARP 0x80 0x80 0x80 0x80 0x80 0x80 # faked nt as linux; unix consensus +syscon iff IFF_POINTOPOINT 0x10 0x10 0x10 0x10 0x10 0x10 # point-to-point; faked nt as linux; unix consensus +syscon iff IFF_PROMISC 0x100 0x100 0x100 0x100 0x100 0 # in packet capture mode; unix consensus syscon iff IFF_RUNNING 0x40 0x40 0x40 0x40 0x40 0 # unix consensus syscon iff IFF_NOTRAILERS 0x20 0x20 0 0 0 0 syscon iff IFF_AUTOMEDIA 0x4000 0 0 0 0 0 diff --git a/libc/sysv/consts/IFF_ALLMULTI.S b/libc/sysv/consts/IFF_ALLMULTI.S index c9f5b9b6b..2857d6be1 100644 --- a/libc/sysv/consts/IFF_ALLMULTI.S +++ b/libc/sysv/consts/IFF_ALLMULTI.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon iff,IFF_ALLMULTI,0x0200,0x0200,0x0200,0x0200,0x0200,0 +.syscon iff,IFF_ALLMULTI,0x0200,0x0200,0x0200,0x0200,0x0200,0x0200 diff --git a/libc/sysv/consts/IFF_DEBUG.S b/libc/sysv/consts/IFF_DEBUG.S index 687689aea..0e811d455 100644 --- a/libc/sysv/consts/IFF_DEBUG.S +++ b/libc/sysv/consts/IFF_DEBUG.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon iff,IFF_DEBUG,4,4,4,4,4,0 +.syscon iff,IFF_DEBUG,4,4,4,4,4,4 diff --git a/libc/sysv/consts/IFF_MULTICAST.S b/libc/sysv/consts/IFF_MULTICAST.S index 75cecbeca..8f158e689 100644 --- a/libc/sysv/consts/IFF_MULTICAST.S +++ b/libc/sysv/consts/IFF_MULTICAST.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon iff,IFF_MULTICAST,0x1000,0x8000,0x8000,0x8000,0x8000,0x10 +.syscon iff,IFF_MULTICAST,0x1000,0x8000,0x8000,0x8000,0x8000,0x1000 diff --git a/libc/sysv/consts/IFF_NOARP.S b/libc/sysv/consts/IFF_NOARP.S index 3a5ff841f..bffe6175c 100644 --- a/libc/sysv/consts/IFF_NOARP.S +++ b/libc/sysv/consts/IFF_NOARP.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon iff,IFF_NOARP,0x80,0x80,0x80,0x80,0x80,0 +.syscon iff,IFF_NOARP,0x80,0x80,0x80,0x80,0x80,0x80 diff --git a/libc/sysv/consts/IFF_POINTOPOINT.S b/libc/sysv/consts/IFF_POINTOPOINT.S index 6924ed6ac..894fe8d56 100644 --- a/libc/sysv/consts/IFF_POINTOPOINT.S +++ b/libc/sysv/consts/IFF_POINTOPOINT.S @@ -1,2 +1,2 @@ #include "libc/sysv/consts/syscon.internal.h" -.syscon iff,IFF_POINTOPOINT,0x10,0x10,0x10,0x10,0x10,0 +.syscon iff,IFF_POINTOPOINT,0x10,0x10,0x10,0x10,0x10,0x10 diff --git a/libc/sysv/consts/IFF_PROIFF.S b/libc/sysv/consts/IFF_PROIFF.S deleted file mode 100644 index 1aad79521..000000000 --- a/libc/sysv/consts/IFF_PROIFF.S +++ /dev/null @@ -1,2 +0,0 @@ -#include "libc/sysv/consts/syscon.internal.h" -.syscon iff,IFF_PROIFF,0x0100,0x0100,0x0100,0x0100,0x0100,0 diff --git a/libc/sysv/consts/IFF_PROMISC.S b/libc/sysv/consts/IFF_PROMISC.S new file mode 100644 index 000000000..be1f05540 --- /dev/null +++ b/libc/sysv/consts/IFF_PROMISC.S @@ -0,0 +1,2 @@ +#include "libc/sysv/consts/syscon.internal.h" +.syscon iff,IFF_PROMISC,0x100,0x100,0x100,0x100,0x100,0 diff --git a/libc/sysv/consts/IFF_UP.S b/libc/sysv/consts/IFF_UP.S new file mode 100644 index 000000000..f58b798fe --- /dev/null +++ b/libc/sysv/consts/IFF_UP.S @@ -0,0 +1,2 @@ +#include "libc/sysv/consts/syscon.internal.h" +.syscon iff,IFF_UP,1,1,1,1,1,1 diff --git a/libc/sysv/consts/iff.h b/libc/sysv/consts/iff.h index da4f17c03..22d3fa5f8 100644 --- a/libc/sysv/consts/iff.h +++ b/libc/sysv/consts/iff.h @@ -1,26 +1,9 @@ #ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_IFF_H_ #define COSMOPOLITAN_LIBC_SYSV_CONSTS_IFF_H_ -#include "libc/runtime/symbolic.h" - -#define IFF_ALLMULTI SYMBOLIC(IFF_ALLMULTI) -#define IFF_AUTOMEDIA SYMBOLIC(IFF_AUTOMEDIA) -#define IFF_BROADCAST SYMBOLIC(IFF_BROADCAST) -#define IFF_DEBUG SYMBOLIC(IFF_DEBUG) -#define IFF_DYNAMIC SYMBOLIC(IFF_DYNAMIC) -#define IFF_LOOPBACK SYMBOLIC(IFF_LOOPBACK) -#define IFF_MASTER SYMBOLIC(IFF_MASTER) -#define IFF_MULTICAST SYMBOLIC(IFF_MULTICAST) -#define IFF_NOARP SYMBOLIC(IFF_NOARP) -#define IFF_NOTRAILERS SYMBOLIC(IFF_NOTRAILERS) -#define IFF_POINTOPOINT SYMBOLIC(IFF_POINTOPOINT) -#define IFF_PORTSEL SYMBOLIC(IFF_PORTSEL) -#define IFF_PROMISC SYMBOLIC(IFF_PROMISC) -#define IFF_RUNNING SYMBOLIC(IFF_RUNNING) -#define IFF_SLAVE SYMBOLIC(IFF_SLAVE) - #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ +extern const long IFF_UP; extern const long IFF_ALLMULTI; extern const long IFF_AUTOMEDIA; extern const long IFF_BROADCAST; @@ -39,4 +22,22 @@ extern const long IFF_SLAVE; COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ + +#define IFF_UP 1 +#define IFF_BROADCAST 2 +#define IFF_DEBUG 4 +#define IFF_LOOPBACK 8 +#define IFF_ALLMULTI IFF_ALLMULTI +#define IFF_AUTOMEDIA IFF_AUTOMEDIA +#define IFF_DYNAMIC IFF_DYNAMIC +#define IFF_MASTER IFF_MASTER +#define IFF_MULTICAST IFF_MULTICAST +#define IFF_NOARP IFF_NOARP +#define IFF_NOTRAILERS IFF_NOTRAILERS +#define IFF_POINTOPOINT IFF_POINTOPOINT +#define IFF_PORTSEL IFF_PORTSEL +#define IFF_PROMISC IFF_PROMISC +#define IFF_RUNNING IFF_RUNNING +#define IFF_SLAVE IFF_SLAVE + #endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_IFF_H_ */ diff --git a/test/libc/calls/ioctl_siocgifconf_test.c b/test/libc/calls/ioctl_siocgifconf_test.c new file mode 100644 index 000000000..15c3b5358 --- /dev/null +++ b/test/libc/calls/ioctl_siocgifconf_test.c @@ -0,0 +1,70 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ Permission to use, copy, modify, and/or distribute this software for │ +│ any purpose with or without fee is hereby granted, provided that the │ +│ above copyright notice and this permission notice appear in all copies. │ +│ │ +│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ +│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ +│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ +│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ +│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ +│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ +│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ +│ PERFORMANCE OF THIS SOFTWARE. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/bits/bits.h" +#include "libc/calls/calls.h" +#include "libc/calls/internal.h" +#include "libc/calls/ioctl.h" +#include "libc/log/check.h" +#include "libc/log/log.h" +#include "libc/mem/mem.h" +#include "libc/runtime/gc.internal.h" +#include "libc/sock/sock.h" +#include "libc/stdio/stdio.h" +#include "libc/sysv/consts/af.h" +#include "libc/sysv/consts/ipproto.h" +#include "libc/sysv/consts/sio.h" +#include "libc/sysv/consts/sock.h" +#include "libc/testlib/testlib.h" + +TEST(ioctl_siocgifconf, test) { + size_t n; + char *data; + int socketfd; + struct ifreq *ifr; + struct ifconf conf; + char addrbuf[1024]; + uint32_t ip, netmask; + bool foundloopback = false; + data = gc(malloc((n = 4096))); + ASSERT_NE(-1, (socketfd = socket(AF_INET, SOCK_DGRAM, 0))); + conf.ifc_buf = data; + conf.ifc_len = n; + ASSERT_NE(-1, ioctl(socketfd, SIOCGIFCONF, &conf)); + for (ifr = (struct ifreq *)data; (char *)ifr < data + conf.ifc_len; ++ifr) { + if (ifr->ifr_addr.sa_family != AF_INET) continue; + ip = ntohl(((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr); + EXPECT_NE(-1, ioctl(socketfd, SIOCGIFNETMASK, ifr)); + netmask = ntohl(((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr); +#if 0 + fprintf(stderr, + "%s %x %d\n" + " ip %hhu.%hhu.%hhu.%hhu\n" + " netmask %hhu.%hhu.%hhu.%hhu\n" + "\n", + ifr->ifr_name, ip, ifr->ifr_addr.sa_family, ip >> 24, ip >> 16, + ip >> 8, ip, netmask >> 24, netmask >> 16, netmask >> 8, netmask); +#endif + if (ip == 0x7f000001) { + foundloopback = true; + EXPECT_EQ(0xFF000000, netmask); + } + } + EXPECT_TRUE(foundloopback); + ASSERT_NE(-1, close(socketfd)); +} diff --git a/test/libc/calls/test.mk b/test/libc/calls/test.mk index 9e24ded53..0ac4572fe 100644 --- a/test/libc/calls/test.mk +++ b/test/libc/calls/test.mk @@ -25,6 +25,7 @@ TEST_LIBC_CALLS_CHECKS = \ TEST_LIBC_CALLS_DIRECTDEPS = \ LIBC_CALLS \ + LIBC_SOCK \ LIBC_FMT \ LIBC_INTRIN \ LIBC_LOG \ @@ -32,6 +33,7 @@ TEST_LIBC_CALLS_DIRECTDEPS = \ LIBC_NEXGEN32E \ LIBC_RAND \ LIBC_STDIO \ + LIBC_SYSV_CALLS \ LIBC_RUNTIME \ LIBC_STR \ LIBC_STUBS \ diff --git a/test/libc/release/clang.sh b/test/libc/release/clang.sh index 0c891383e..5cb899b4e 100755 --- a/test/libc/release/clang.sh +++ b/test/libc/release/clang.sh @@ -12,6 +12,7 @@ if CLANG=$(command -v clang); then -fno-pie \ -nostdlib \ -nostdinc \ + -fuse-ld=lld \ -mno-red-zone \ -Wl,-T,o/$MODE/ape/ape.lds \ -include o/cosmopolitan.h \ diff --git a/test/libc/release/lld.sh b/test/libc/release/lld.sh new file mode 100755 index 000000000..c6656f433 --- /dev/null +++ b/test/libc/release/lld.sh @@ -0,0 +1,27 @@ +#!/bin/sh +#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐ +#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘ + +# TODO(jart): implement me + +if CLANG=$(command -v clang); then + $CLANG \ + -o o/$MODE/test/libc/release/smokeclang.com.dbg \ + -Os \ + -Wall \ + -Werror \ + -static \ + -fno-pie \ + -nostdlib \ + -nostdinc \ + -mno-red-zone \ + -Wl,-T,o/$MODE/ape/ape.lds \ + -include o/cosmopolitan.h \ + test/libc/release/smoke.c \ + o/$MODE/libc/crt/crt.o \ + o/$MODE/ape/ape.o \ + o/$MODE/cosmopolitan.a || exit + o/$MODE/test/libc/release/smokeclang.com.dbg || exit +fi + +touch o/$MODE/test/libc/release/clang.ok diff --git a/test/libc/release/test.mk b/test/libc/release/test.mk index 872f9395d..b8b295cb2 100644 --- a/test/libc/release/test.mk +++ b/test/libc/release/test.mk @@ -125,6 +125,16 @@ o/$(MODE)/test/libc/release/clang.ok: \ o/$(MODE)/cosmopolitan.a @$(COMPILE) -ASHTEST -T$< $< +o/$(MODE)/test/libc/release/lld.ok: \ + test/libc/release/lld.sh \ + test/libc/release/smoke.c \ + o/cosmopolitan.h \ + o/$(MODE)/ape/ape.lds \ + o/$(MODE)/libc/crt/crt.o \ + o/$(MODE)/ape/ape.o \ + o/$(MODE)/cosmopolitan.a + @$(COMPILE) -ASHTEST -T$< $< + o/$(MODE)/test/libc/release/metal.ok: \ test/libc/release/metal.sh \ o/$(MODE)/examples/hello.com \ @@ -148,5 +158,6 @@ o/$(MODE)/test/libc/release: \ o/$(MODE)/test/libc/release/smokeansi.com \ o/$(MODE)/test/libc/release/smokeansi.com.runs \ o/$(MODE)/test/libc/release/clang.ok \ + o/$(MODE)/test/libc/release/lld.ok \ o/$(MODE)/test/libc/release/emulate.ok \ o/$(MODE)/test/libc/release/metal.ok diff --git a/third_party/infozip/zip/zip.c b/third_party/infozip/zip/zip.c index 216059129..86e526010 100644 --- a/third_party/infozip/zip/zip.c +++ b/third_party/infozip/zip/zip.c @@ -1433,7 +1433,7 @@ local void check_zipfile(zipname, zippath) int result; /* Tell picky compilers to shut up about unused variables */ - zippath = zippath; + (void)zippath; if (unzip_path) { /* user gave us a path to some unzip (may not be UnZip) */ @@ -1798,7 +1798,7 @@ ZCONST char *zfn; char *prompt; /* Tell picky compilers to shut up about unused variables */ - zfn = zfn; + (void)zfn; prompt = (modeflag == ZP_PW_VERIFY) ? "Verify password: " : "Enter password: "; @@ -1817,7 +1817,7 @@ int size; ZCONST char *zfn; { /* Tell picky compilers to shut up about unused variables */ - modeflag = modeflag; pwbuf = pwbuf; size = size; zfn = zfn; + (void)modeflag; (void)pwbuf; (void)size; (void)zfn; return ZE_LOGIC; /* This function should never be called! */ } diff --git a/third_party/infozip/zip/zipfile.c b/third_party/infozip/zip/zipfile.c index b4b22c825..81587071a 100644 --- a/third_party/infozip/zip/zipfile.c +++ b/third_party/infozip/zip/zipfile.c @@ -29,7 +29,9 @@ #include "libc/str/str.h" #include "libc/fmt/fmt.h" +#if defined(__GNUC__) && !defined(__llvm__) #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif #ifdef VMS # include "vms/vms.h" diff --git a/third_party/mbedtls/getalertdescription.c b/third_party/mbedtls/getalertdescription.c index d77149186..641418494 100644 --- a/third_party/mbedtls/getalertdescription.c +++ b/third_party/mbedtls/getalertdescription.c @@ -25,7 +25,7 @@ * @see RFC5246 §7.2 */ const char *GetAlertDescription(unsigned char x) { - static char buf[4]; + static char buf[21]; switch (x) { case MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY: /* 0 */ return "close_notify"; diff --git a/third_party/sqlite3/btree.c b/third_party/sqlite3/btree.c index d5e9e0544..8a5f79d63 100644 --- a/third_party/sqlite3/btree.c +++ b/third_party/sqlite3/btree.c @@ -14,7 +14,10 @@ ** Including a description of file format and an overview of operation. */ #include "third_party/sqlite3/btreeInt.inc" + +#if defined(__GNUC__) && !defined(__llvm__) #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif /* clang-format off */ diff --git a/third_party/sqlite3/sqlite3session.c b/third_party/sqlite3/sqlite3session.c index 81edc3789..095cb12c8 100644 --- a/third_party/sqlite3/sqlite3session.c +++ b/third_party/sqlite3/sqlite3session.c @@ -3,7 +3,10 @@ #include "libc/assert.h" #include "libc/str/str.h" #include "third_party/sqlite3/sqlite3session.inc" + +#if defined(__GNUC__) && !defined(__llvm__) #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif #ifndef SQLITE_AMALGAMATION #include "third_party/sqlite3/sqliteInt.inc" diff --git a/tool/net/redbean.c b/tool/net/redbean.c index d4ead725e..dc5993ebf 100644 --- a/tool/net/redbean.c +++ b/tool/net/redbean.c @@ -646,11 +646,6 @@ static long FindRedirect(const char *s, size_t n) { return -1; } -static wontreturn void CrashCertificate(const char *name, const char *path) { - fprintf(stderr, "error: failed to load %s: %s\n", name, path); - exit(1); -} - static void LogCertificate(const char *msg, mbedtls_x509_crt *cert) { char *s; size_t n;