mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-21 09:02:17 +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/stack.h"
|
||||
#include "libc/serialize.h"
|
||||
#include "libc/sock/in.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/struct/ifconf.h"
|
||||
#include "libc/sock/struct/ifreq.h"
|
||||
|
@ -533,8 +534,7 @@ static int ioctl_siocgifconf_sysv(int fd, struct ifconf *ifc) {
|
|||
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;
|
||||
if (fam == AF_INET) {
|
||||
ip = READ32BE(p + 20);
|
||||
bzero(req, sizeof(*req));
|
||||
memcpy(req->ifr_name, p, 16);
|
||||
|
@ -542,6 +542,26 @@ static int ioctl_siocgifconf_sysv(int fd, struct ifconf *ifc) {
|
|||
req->ifr_addr.sa_family = fam;
|
||||
((struct sockaddr_in *)&req->ifr_addr)->sin_addr.s_addr = htonl(ip);
|
||||
++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 */
|
||||
}
|
||||
|
|
|
@ -45,3 +45,8 @@ uint64_t(bswap_64)(uint64_t x) {
|
|||
(0x00ff000000000000ull & x) >> 050 |
|
||||
(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 uint32_t bswap_32(uint32_t) pureconst;
|
||||
libcesque uint64_t bswap_64(uint64_t) pureconst;
|
||||
libcesque uint128_t bswap_128(uint128_t) pureconst;
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
||||
#define bswap_16(x) __builtin_bswap16(x)
|
||||
#define bswap_32(x) __builtin_bswap32(x)
|
||||
#define bswap_64(x) __builtin_bswap64(x)
|
||||
#define bswap_128(x) __builtin_bswap128(x)
|
||||
#endif /* defined(__GNUC__) && !defined(__STRICT_ANSI__) */
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
#define htobe64(x) bswap_64(x)
|
||||
#define be64toh(x) bswap_64(x)
|
||||
#define betoh64(x) bswap_64(x)
|
||||
#define htobe128(x) bswap_128(x)
|
||||
#define be128toh(x) bswap_128(x)
|
||||
#define betoh128(x) bswap_128(x)
|
||||
#define htole16(x) (uint16_t)(x)
|
||||
#define le16toh(x) (uint16_t)(x)
|
||||
#define letoh16(x) (uint16_t)(x)
|
||||
|
@ -26,6 +29,9 @@
|
|||
#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
|
||||
#define htobe16(x) (uint16_t)(x)
|
||||
#define be16toh(x) (uint16_t)(x)
|
||||
|
@ -36,6 +42,9 @@
|
|||
#define htobe64(x) (uint64_t)(x)
|
||||
#define be64toh(x) (uint64_t)(x)
|
||||
#define betoh64(x) (uint64_t)(x)
|
||||
#define htobe128(x) (uint128_t)(x)
|
||||
#define be128toh(x) (uint128_t)(x)
|
||||
#define betoh128(x) (uint128_t)(x)
|
||||
#define htole16(x) bswap_16(x)
|
||||
#define le16toh(x) bswap_16(x)
|
||||
#define letoh16(x) bswap_16(x)
|
||||
|
@ -45,6 +54,9 @@
|
|||
#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 /* COSMOPOLITAN_LIBC_BITS_NEWBIE_H_ */
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/newbie.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/sock/sock.h"
|
||||
|
@ -34,6 +35,9 @@
|
|||
#include "libc/sysv/consts/sio.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
|
||||
#define SIOCGIFAFLAG_IN6 3240126793 // bsd
|
||||
#define SIOCGIFNETMASK_IN6 3240126757 // bsd
|
||||
|
||||
struct IfAddr {
|
||||
struct ifaddrs ifaddrs;
|
||||
char name[IFNAMSIZ];
|
||||
|
@ -142,27 +146,27 @@ static int getifaddrs_linux_ip6(struct ifconf *conf) {
|
|||
* @see tool/viz/getifaddrs.c for example code
|
||||
*/
|
||||
int getifaddrs(struct ifaddrs **out_ifpp) {
|
||||
// printf("%d\n", sizeof(struct ifreq));
|
||||
int rc = -1;
|
||||
int fd;
|
||||
int rc = 0;
|
||||
int fd, fd6 = -1;
|
||||
if ((fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0)) != -1) {
|
||||
char *data;
|
||||
size_t size;
|
||||
if ((data = malloc((size = 16384)))) {
|
||||
struct ifconf conf;
|
||||
struct ifconf conf, confl6;
|
||||
conf.ifc_buf = data;
|
||||
conf.ifc_len = size;
|
||||
if (!ioctl(fd, SIOCGIFCONF, &conf)) {
|
||||
if (IsLinux()) {
|
||||
struct ifconf confl6;
|
||||
confl6.ifc_buf = data + conf.ifc_len;
|
||||
confl6.ifc_len = size - conf.ifc_len;
|
||||
if ((rc = getifaddrs_linux_ip6(&confl6)))
|
||||
if (IsLinux()) {
|
||||
rc = getifaddrs_linux_ip6(&confl6);
|
||||
}
|
||||
if (rc)
|
||||
return rc;
|
||||
conf.ifc_len += confl6.ifc_len;
|
||||
}
|
||||
|
||||
struct ifaddrs *res = 0;
|
||||
rc = -1;
|
||||
for (struct ifreq *ifr = (struct ifreq *)data;
|
||||
(char *)ifr < data + conf.ifc_len; ++ifr) {
|
||||
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_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_flags = ifr->ifr6_flags;
|
||||
|
||||
memcpy(&addr6->name, &ifr->ifr_name, IFNAMSIZ);
|
||||
|
||||
addr6->addr.sin6_family = AF_INET6;
|
||||
addr6->addr.sin6_port = 0;
|
||||
|
@ -222,10 +227,33 @@ int getifaddrs(struct ifaddrs **out_ifpp) {
|
|||
addr6->netmask.sin6_port = 0;
|
||||
addr6->netmask.sin6_flowinfo = 0;
|
||||
addr6->addr.sin6_scope_id = ifr->ifr6_ifindex;
|
||||
memcpy(&addr6->netmask.sin6_addr, &ifr->ifr6_addr,
|
||||
|
||||
if (IsBsd()) { // on bsd we miss prefixlen and addr flags
|
||||
if (fd6 == -1) {
|
||||
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));
|
||||
*((uint128_t *)&(addr6->netmask.sin6_addr)) &=
|
||||
(UINT128_MAX >> ifr->ifr6_prefixlen);
|
||||
}
|
||||
} 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)) {
|
||||
addr6->ifaddrs.ifa_flags = ifr->ifr_flags;
|
||||
|
@ -243,6 +271,9 @@ int getifaddrs(struct ifaddrs **out_ifpp) {
|
|||
free(data);
|
||||
}
|
||||
close(fd);
|
||||
if (fd6 != -1) {
|
||||
close(fd6);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue