mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-21 17:12:18 +00:00
Merge abab1dec63
into f1e83d5240
This commit is contained in:
commit
2b491390b6
5 changed files with 134 additions and 64 deletions
|
@ -43,6 +43,7 @@
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/runtime/stack.h"
|
#include "libc/runtime/stack.h"
|
||||||
#include "libc/serialize.h"
|
#include "libc/serialize.h"
|
||||||
|
#include "libc/sock/in.h"
|
||||||
#include "libc/sock/internal.h"
|
#include "libc/sock/internal.h"
|
||||||
#include "libc/sock/struct/ifconf.h"
|
#include "libc/sock/struct/ifconf.h"
|
||||||
#include "libc/sock/struct/ifreq.h"
|
#include "libc/sock/struct/ifreq.h"
|
||||||
|
@ -533,15 +534,34 @@ static int ioctl_siocgifconf_sysv(int fd, struct ifconf *ifc) {
|
||||||
for (p = b, e = p + MIN(bufMax, READ32LE(ifcBsd)); p + 16 + 16 <= e;
|
for (p = b, e = p + MIN(bufMax, READ32LE(ifcBsd)); p + 16 + 16 <= e;
|
||||||
p += IsBsd() ? 16 + MAX(16, p[16] & 255) : 40) {
|
p += IsBsd() ? 16 + MAX(16, p[16] & 255) : 40) {
|
||||||
fam = p[IsBsd() ? 17 : 16] & 255;
|
fam = p[IsBsd() ? 17 : 16] & 255;
|
||||||
if (fam != AF_INET)
|
if (fam == AF_INET) {
|
||||||
continue;
|
ip = READ32BE(p + 20);
|
||||||
ip = READ32BE(p + 20);
|
bzero(req, sizeof(*req));
|
||||||
bzero(req, sizeof(*req));
|
memcpy(req->ifr_name, p, 16);
|
||||||
memcpy(req->ifr_name, p, 16);
|
memcpy(&req->ifr_addr, p + 16, 16);
|
||||||
memcpy(&req->ifr_addr, p + 16, 16);
|
req->ifr_addr.sa_family = fam;
|
||||||
req->ifr_addr.sa_family = fam;
|
((struct sockaddr_in *)&req->ifr_addr)->sin_addr.s_addr = htonl(ip);
|
||||||
((struct sockaddr_in *)&req->ifr_addr)->sin_addr.s_addr = htonl(ip);
|
++req;
|
||||||
++req;
|
} else if (fam == AF_INET6) {
|
||||||
|
// Only BSD systems returns AF_INET6 addresses with SIOCGIFCONF
|
||||||
|
// BSD don't return flags or prefix length, need to get them later
|
||||||
|
bzero(req, sizeof(*req));
|
||||||
|
memcpy(req->ifr_name, p, 16);
|
||||||
|
void *addr6 = p + 24;
|
||||||
|
if (IN6_IS_ADDR_LINKLOCAL(addr6)) {
|
||||||
|
// link-local bsd special https://stackoverflow.com/q/5888359/2838914
|
||||||
|
req->ifr6_ifindex = ntohs(*((uint16_t *)(p + 26)));
|
||||||
|
*((uint16_t *)(p + 26)) = 0x0;
|
||||||
|
req->ifr6_scope = 0x20; // link
|
||||||
|
} else if (IN6_IS_ADDR_SITELOCAL(addr6)) {
|
||||||
|
req->ifr6_scope = 0x40; // site
|
||||||
|
} else if (IN6_IS_ADDR_LOOPBACK(addr6)) {
|
||||||
|
req->ifr6_scope = 0x10; // host
|
||||||
|
}
|
||||||
|
memcpy(&req->ifr6_addr, addr6, 16);
|
||||||
|
req->ifr_addr.sa_family = fam;
|
||||||
|
++req;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ifc->ifc_len = (char *)req - ifc->ifc_buf; /* Adjust len */
|
ifc->ifc_len = (char *)req - ifc->ifc_buf; /* Adjust len */
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,3 +45,8 @@ uint64_t(bswap_64)(uint64_t x) {
|
||||||
(0x00ff000000000000ull & x) >> 050 |
|
(0x00ff000000000000ull & x) >> 050 |
|
||||||
(0xff00000000000000ull & x) >> 070;
|
(0xff00000000000000ull & x) >> 070;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint128_t(bswap_128)(uint128_t x) {
|
||||||
|
return ((uint128_t)bswap_64((uint64_t)x) << 64) |
|
||||||
|
(uint128_t)bswap_64((uint64_t)(x >> 64));
|
||||||
|
}
|
||||||
|
|
|
@ -5,11 +5,13 @@ COSMOPOLITAN_C_START_
|
||||||
libcesque uint16_t bswap_16(uint16_t) pureconst;
|
libcesque uint16_t bswap_16(uint16_t) pureconst;
|
||||||
libcesque uint32_t bswap_32(uint32_t) pureconst;
|
libcesque uint32_t bswap_32(uint32_t) pureconst;
|
||||||
libcesque uint64_t bswap_64(uint64_t) pureconst;
|
libcesque uint64_t bswap_64(uint64_t) pureconst;
|
||||||
|
libcesque uint128_t bswap_128(uint128_t) pureconst;
|
||||||
|
|
||||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||||
#define bswap_16(x) __builtin_bswap16(x)
|
#define bswap_16(x) __builtin_bswap16(x)
|
||||||
#define bswap_32(x) __builtin_bswap32(x)
|
#define bswap_32(x) __builtin_bswap32(x)
|
||||||
#define bswap_64(x) __builtin_bswap64(x)
|
#define bswap_64(x) __builtin_bswap64(x)
|
||||||
|
#define bswap_128(x) __builtin_bswap128(x)
|
||||||
#endif /* defined(__GNUC__) && !defined(__STRICT_ANSI__) */
|
#endif /* defined(__GNUC__) && !defined(__STRICT_ANSI__) */
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
|
|
|
@ -8,43 +8,55 @@
|
||||||
#define PDP_ENDIAN __ORDER_PDP_ENDIAN__
|
#define PDP_ENDIAN __ORDER_PDP_ENDIAN__
|
||||||
|
|
||||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
#define htobe16(x) bswap_16(x)
|
#define htobe16(x) bswap_16(x)
|
||||||
#define be16toh(x) bswap_16(x)
|
#define be16toh(x) bswap_16(x)
|
||||||
#define betoh16(x) bswap_16(x)
|
#define betoh16(x) bswap_16(x)
|
||||||
#define htobe32(x) bswap_32(x)
|
#define htobe32(x) bswap_32(x)
|
||||||
#define be32toh(x) bswap_32(x)
|
#define be32toh(x) bswap_32(x)
|
||||||
#define betoh32(x) bswap_32(x)
|
#define betoh32(x) bswap_32(x)
|
||||||
#define htobe64(x) bswap_64(x)
|
#define htobe64(x) bswap_64(x)
|
||||||
#define be64toh(x) bswap_64(x)
|
#define be64toh(x) bswap_64(x)
|
||||||
#define betoh64(x) bswap_64(x)
|
#define betoh64(x) bswap_64(x)
|
||||||
#define htole16(x) (uint16_t)(x)
|
#define htobe128(x) bswap_128(x)
|
||||||
#define le16toh(x) (uint16_t)(x)
|
#define be128toh(x) bswap_128(x)
|
||||||
#define letoh16(x) (uint16_t)(x)
|
#define betoh128(x) bswap_128(x)
|
||||||
#define htole32(x) (uint32_t)(x)
|
#define htole16(x) (uint16_t)(x)
|
||||||
#define le32toh(x) (uint32_t)(x)
|
#define le16toh(x) (uint16_t)(x)
|
||||||
#define letoh32(x) (uint32_t)(x)
|
#define letoh16(x) (uint16_t)(x)
|
||||||
#define htole64(x) (uint64_t)(x)
|
#define htole32(x) (uint32_t)(x)
|
||||||
#define le64toh(x) (uint64_t)(x)
|
#define le32toh(x) (uint32_t)(x)
|
||||||
#define letoh64(x) (uint64_t)(x)
|
#define letoh32(x) (uint32_t)(x)
|
||||||
|
#define htole64(x) (uint64_t)(x)
|
||||||
|
#define le64toh(x) (uint64_t)(x)
|
||||||
|
#define letoh64(x) (uint64_t)(x)
|
||||||
|
#define htole128(x) (uint128_t)(x)
|
||||||
|
#define le128toh(x) (uint128_t)(x)
|
||||||
|
#define letoh128(x) (uint128_t)(x)
|
||||||
#else
|
#else
|
||||||
#define htobe16(x) (uint16_t)(x)
|
#define htobe16(x) (uint16_t)(x)
|
||||||
#define be16toh(x) (uint16_t)(x)
|
#define be16toh(x) (uint16_t)(x)
|
||||||
#define betoh16(x) (uint16_t)(x)
|
#define betoh16(x) (uint16_t)(x)
|
||||||
#define htobe32(x) (uint32_t)(x)
|
#define htobe32(x) (uint32_t)(x)
|
||||||
#define be32toh(x) (uint32_t)(x)
|
#define be32toh(x) (uint32_t)(x)
|
||||||
#define betoh32(x) (uint32_t)(x)
|
#define betoh32(x) (uint32_t)(x)
|
||||||
#define htobe64(x) (uint64_t)(x)
|
#define htobe64(x) (uint64_t)(x)
|
||||||
#define be64toh(x) (uint64_t)(x)
|
#define be64toh(x) (uint64_t)(x)
|
||||||
#define betoh64(x) (uint64_t)(x)
|
#define betoh64(x) (uint64_t)(x)
|
||||||
#define htole16(x) bswap_16(x)
|
#define htobe128(x) (uint128_t)(x)
|
||||||
#define le16toh(x) bswap_16(x)
|
#define be128toh(x) (uint128_t)(x)
|
||||||
#define letoh16(x) bswap_16(x)
|
#define betoh128(x) (uint128_t)(x)
|
||||||
#define htole32(x) bswap_32(x)
|
#define htole16(x) bswap_16(x)
|
||||||
#define le32toh(x) bswap_32(x)
|
#define le16toh(x) bswap_16(x)
|
||||||
#define letoh32(x) bswap_32(x)
|
#define letoh16(x) bswap_16(x)
|
||||||
#define htole64(x) bswap_64(x)
|
#define htole32(x) bswap_32(x)
|
||||||
#define le64toh(x) bswap_64(x)
|
#define le32toh(x) bswap_32(x)
|
||||||
#define letoh64(x) bswap_64(x)
|
#define letoh32(x) bswap_32(x)
|
||||||
|
#define htole64(x) bswap_64(x)
|
||||||
|
#define le64toh(x) bswap_64(x)
|
||||||
|
#define letoh64(x) bswap_64(x)
|
||||||
|
#define htole128(x) bswap_128(x)
|
||||||
|
#define le128toh(x) bswap_128(x)
|
||||||
|
#define letoh128(x) bswap_128(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* COSMOPOLITAN_LIBC_BITS_NEWBIE_H_ */
|
#endif /* COSMOPOLITAN_LIBC_BITS_NEWBIE_H_ */
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/syscall-sysv.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/newbie.h"
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/sock/sock.h"
|
#include "libc/sock/sock.h"
|
||||||
|
@ -34,6 +35,9 @@
|
||||||
#include "libc/sysv/consts/sio.h"
|
#include "libc/sysv/consts/sio.h"
|
||||||
#include "libc/sysv/consts/sock.h"
|
#include "libc/sysv/consts/sock.h"
|
||||||
|
|
||||||
|
#define SIOCGIFAFLAG_IN6 3240126793 // bsd
|
||||||
|
#define SIOCGIFNETMASK_IN6 3240126757 // bsd
|
||||||
|
|
||||||
struct IfAddr {
|
struct IfAddr {
|
||||||
struct ifaddrs ifaddrs;
|
struct ifaddrs ifaddrs;
|
||||||
char name[IFNAMSIZ];
|
char name[IFNAMSIZ];
|
||||||
|
@ -142,27 +146,27 @@ static int getifaddrs_linux_ip6(struct ifconf *conf) {
|
||||||
* @see tool/viz/getifaddrs.c for example code
|
* @see tool/viz/getifaddrs.c for example code
|
||||||
*/
|
*/
|
||||||
int getifaddrs(struct ifaddrs **out_ifpp) {
|
int getifaddrs(struct ifaddrs **out_ifpp) {
|
||||||
// printf("%d\n", sizeof(struct ifreq));
|
int rc = 0;
|
||||||
int rc = -1;
|
int fd, fd6 = -1;
|
||||||
int fd;
|
|
||||||
if ((fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0)) != -1) {
|
if ((fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0)) != -1) {
|
||||||
char *data;
|
char *data;
|
||||||
size_t size;
|
size_t size;
|
||||||
if ((data = malloc((size = 16384)))) {
|
if ((data = malloc((size = 16384)))) {
|
||||||
struct ifconf conf;
|
struct ifconf conf, confl6;
|
||||||
conf.ifc_buf = data;
|
conf.ifc_buf = data;
|
||||||
conf.ifc_len = size;
|
conf.ifc_len = size;
|
||||||
if (!ioctl(fd, SIOCGIFCONF, &conf)) {
|
if (!ioctl(fd, SIOCGIFCONF, &conf)) {
|
||||||
|
confl6.ifc_buf = data + conf.ifc_len;
|
||||||
|
confl6.ifc_len = size - conf.ifc_len;
|
||||||
if (IsLinux()) {
|
if (IsLinux()) {
|
||||||
struct ifconf confl6;
|
rc = getifaddrs_linux_ip6(&confl6);
|
||||||
confl6.ifc_buf = data + conf.ifc_len;
|
|
||||||
confl6.ifc_len = size - conf.ifc_len;
|
|
||||||
if ((rc = getifaddrs_linux_ip6(&confl6)))
|
|
||||||
return rc;
|
|
||||||
conf.ifc_len += confl6.ifc_len;
|
|
||||||
}
|
}
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
conf.ifc_len += confl6.ifc_len;
|
||||||
|
|
||||||
struct ifaddrs *res = 0;
|
struct ifaddrs *res = 0;
|
||||||
|
rc = -1;
|
||||||
for (struct ifreq *ifr = (struct ifreq *)data;
|
for (struct ifreq *ifr = (struct ifreq *)data;
|
||||||
(char *)ifr < data + conf.ifc_len; ++ifr) {
|
(char *)ifr < data + conf.ifc_len; ++ifr) {
|
||||||
uint16_t family = ifr->ifr_addr.sa_family;
|
uint16_t family = ifr->ifr_addr.sa_family;
|
||||||
|
@ -207,9 +211,10 @@ int getifaddrs(struct ifaddrs **out_ifpp) {
|
||||||
addr6->ifaddrs.ifa_broadaddr = (struct sockaddr *)&addr6->bstaddr;
|
addr6->ifaddrs.ifa_broadaddr = (struct sockaddr *)&addr6->bstaddr;
|
||||||
addr6->ifaddrs.ifa_data = (void *)&addr6->info;
|
addr6->ifaddrs.ifa_data = (void *)&addr6->info;
|
||||||
|
|
||||||
memcpy(&addr6->name, &ifr->ifr_name, IFNAMSIZ);
|
|
||||||
addr6->info.addr_flags = ifr->ifr6_flags;
|
|
||||||
addr6->info.addr_scope = ifr->ifr6_scope;
|
addr6->info.addr_scope = ifr->ifr6_scope;
|
||||||
|
addr6->info.addr_flags = ifr->ifr6_flags;
|
||||||
|
|
||||||
|
memcpy(&addr6->name, &ifr->ifr_name, IFNAMSIZ);
|
||||||
|
|
||||||
addr6->addr.sin6_family = AF_INET6;
|
addr6->addr.sin6_family = AF_INET6;
|
||||||
addr6->addr.sin6_port = 0;
|
addr6->addr.sin6_port = 0;
|
||||||
|
@ -222,10 +227,33 @@ int getifaddrs(struct ifaddrs **out_ifpp) {
|
||||||
addr6->netmask.sin6_port = 0;
|
addr6->netmask.sin6_port = 0;
|
||||||
addr6->netmask.sin6_flowinfo = 0;
|
addr6->netmask.sin6_flowinfo = 0;
|
||||||
addr6->addr.sin6_scope_id = ifr->ifr6_ifindex;
|
addr6->addr.sin6_scope_id = ifr->ifr6_ifindex;
|
||||||
memcpy(&addr6->netmask.sin6_addr, &ifr->ifr6_addr,
|
|
||||||
sizeof(struct in6_addr));
|
if (IsBsd()) { // on bsd we miss prefixlen and addr flags
|
||||||
*((uint128_t *)&(addr6->netmask.sin6_addr)) &=
|
if (fd6 == -1) {
|
||||||
(UINT128_MAX >> ifr->ifr6_prefixlen);
|
fd6 = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||||
|
}
|
||||||
|
uint8_t in6req[288]; // BSD struct in6_ifreq
|
||||||
|
bzero(&in6req, sizeof(in6req));
|
||||||
|
memcpy(&in6req, &ifr->ifr_name, IFNAMSIZ);
|
||||||
|
in6req[16] = 28; // sin6_len sizeof(struct sockaddr_in6_bsd)
|
||||||
|
in6req[17] = AF_INET6; // sin6_family
|
||||||
|
memcpy(&in6req[24], &addr6->addr.sin6_addr,
|
||||||
|
sizeof(struct in6_addr)); // sin6_addr
|
||||||
|
if (!ioctl(fd6, SIOCGIFAFLAG_IN6, &in6req)) {
|
||||||
|
addr6->info.addr_flags =
|
||||||
|
*(int *)(&in6req[16]); // ifru_flags6
|
||||||
|
}
|
||||||
|
in6req[16] = 28; // sin6_len
|
||||||
|
in6req[17] = AF_INET6; // sin6_family
|
||||||
|
if (!ioctl(fd6, SIOCGIFNETMASK_IN6, &in6req)) {
|
||||||
|
memcpy(&(addr6->netmask.sin6_addr), &in6req[24],
|
||||||
|
sizeof(struct in6_addr));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int prefixlen = ifr->ifr6_prefixlen;
|
||||||
|
*((uint128_t *)&(addr6->netmask.sin6_addr)) = htobe128(
|
||||||
|
prefixlen == 0 ? 0 : (UINT128_MAX << (128 - prefixlen)));
|
||||||
|
}
|
||||||
|
|
||||||
if (!ioctl(fd, SIOCGIFFLAGS, ifr)) {
|
if (!ioctl(fd, SIOCGIFFLAGS, ifr)) {
|
||||||
addr6->ifaddrs.ifa_flags = ifr->ifr_flags;
|
addr6->ifaddrs.ifa_flags = ifr->ifr_flags;
|
||||||
|
@ -243,6 +271,9 @@ int getifaddrs(struct ifaddrs **out_ifpp) {
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
|
if (fd6 != -1) {
|
||||||
|
close(fd6);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue