Initial implementation of ioctl SIOCGIFCONF. Untested for most of the platforms yet.

This commit is contained in:
Fabrizio Bertocci 2021-04-10 11:40:23 -04:00
parent f40f97bd07
commit 187eb9ae41
5 changed files with 177 additions and 0 deletions

View file

@ -0,0 +1,61 @@
/*-*- 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 2020 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/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/sysv/consts/o.h"
#include "libc/sock/sock.h"
#include "libc/sock/internal.h"
#include "libc/sysv/errfuns.h"
#include "libc/nt/winsock.h"
// TODO: Remove me
#include "libc/stdio/stdio.h"
#define MAX_INTERFACES 32
/* 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
*/
textwindows int ioctl_siocgifconf_nt(int fd, struct ifconf *ifc) {
struct NtInterfaceInfo iflist[MAX_INTERFACES];
uint32_t dwBytes;
int ret;
int i, count;
if (g_fds.p[fd].kind != kFdSocket) {
return ebadf();
}
ret = WSAIoctl(g_fds.p[fd].handle, kNtSioGetInterfaceList, NULL, 0, &iflist, sizeof(iflist), &dwBytes, NULL, NULL);
if (ret == -1) {
return __winsockerr();
}
count = dwBytes / sizeof(struct NtInterfaceInfo);
printf("CI> SIO_GET_INTERFACE_LIST success:\n");
for (i = 0; i < count; ++i) {
printf("CI>\t #i: %08x\n", i, iflist[i].iiAddress.sin_addr.s_addr);
}
return ret;
}

View file

@ -0,0 +1,51 @@
/*-*- 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 2020 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/calls/internal.h"
#include "libc/sock/sock.h"
#include "libc/sock/internal.h"
#include "libc/sysv/consts/sio.h"
int ioctl_siocgifconf_nt(int, struct ifconf *) hidden;
static int ioctl_siocgifconf_sysv(int fd, struct ifconf *ifc) {
/* Same as the default for now... */
return sys_ioctl(fd, SIOCGIFCONF, ifc);
/*
int rc;
if ((rc = sys_ioctl(fd, SIOCGIFCONF, &ifc)) != -1) {
return rc;
}
return rc;
*/
}
/**
* Returns information about network interfaces.
*
* @see ioctl(fd, SIOCGIFCONF, tio) dispatches here
*/
int ioctl_siocgifconf(int fd, struct ifconf *ifc) {
if (!IsWindows()) {
return ioctl_siocgifconf_sysv(fd, ifc);
} else {
return ioctl_siocgifconf_nt(fd, ifc);
}
}

View file

@ -2,6 +2,7 @@
#define COSMOPOLITAN_LIBC_CALLS_IOCTL_H_
#include "libc/macros.internal.h"
#include "libc/sysv/consts/termios.h"
#include "libc/sysv/consts/sio.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
@ -27,6 +28,7 @@ int ioctl(int, uint64_t, void *);
if (CMP(request, TCSETS)) return ioctl_tcsets(FD, REQUEST, MEMORY); \
if (CMP(request, TCSETSW)) return ioctl_tcsets(FD, REQUEST, MEMORY); \
if (CMP(request, TCSETSF)) return ioctl_tcsets(FD, REQUEST, MEMORY); \
if (CMP(request, SIOCGIFCONF)) return ioctl_siocgifconf(FD, REQUEST, MEMORY); \
} while (0)
int ioctl_tcgets(int, void *);
@ -37,6 +39,7 @@ int ioctl_tiocgwinsz(int, void *);
int ioctl_tiocgwinsz_nt(int, void *);
int ioctl_tiocswinsz(int, void *);
int ioctl_tiocswinsz_nt(int, void *);
int ioctl_siocgifconf(int, uint64_t, void *);
int ioctl_default(int, uint64_t, void *);
forceinline int ioctl_dispatch(int fd, uint64_t request, void *memory) {

View file

@ -85,6 +85,7 @@
#define kNtSioTranslateHandle 0xC800000Du
#define kNtSioUdpConnreset 0x9800000Cu
#define kNtSioUdpNetreset 0x9800000Fu
#define kNtSioGetInterfaceList 0x4008747fu /* _IOR('t', 127, ULONG) */
#define kNtNspNotifyImmediately 0
#define kNtNspNotifyHwnd 1
@ -311,6 +312,13 @@ struct NtFdSet {
int64_t fd_array[64];
};
struct NtInterfaceInfo {
uint64_t iiFlags;
struct sockaddr_in iiAddress;
struct sockaddr_in iiBroadcastAddress;
struct sockaddr_in iiNetmask;
};
/**
* Winsock2 prototypes.
*

View file

@ -75,6 +75,60 @@ struct msghdr { /* Linux+NT ABI */
uint32_t msg_flags; /* MSG_XXX */
};
/*
* Structure used in SIOCGIFCONF request.
* Used to retrieve interface configuration
* for machine (useful for programs which
* must know all networks accessible).
*/
struct ifconf {
int ifc_len; /* size of buffer */
union {
char *ifcu_buf;
struct ifreq *ifcu_req;
} ifc_ifcu;
};
/* Shortcuts to the ifconf buffer or ifreq array */
#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */
#define ifc_req ifc_ifcu.ifcu_req /* array of structures */
#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;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
short int ifru_flags;
int ifru_ivalue;
int ifru_mtu;
} ifr_ifru;
};
# define ifr_name ifr_ifrn.ifrn_name /* interface name */
# define ifr_addr ifr_ifru.ifru_addr /* address */
# define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
# define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
# define ifr_flags ifr_ifru.ifru_flags /* flags */
# define ifr_metric ifr_ifru.ifru_ivalue /* metric */
# define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
# define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */
# define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */
# define ifr_qlen ifr_ifru.ifru_ivalue /* queue length */
# define _IOT_ifreq _IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0)
# 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 *);