From d5a839c724eef9f2ac7e21c99d6750e7d0c2fa3f Mon Sep 17 00:00:00 2001 From: Fabrizio Bertocci Date: Sun, 23 May 2021 16:32:40 -0400 Subject: [PATCH] Added support for SIOCGIFBRDADDR, SIOCGIFDSTADDR, SIOCGIFFLAGS --- libc/calls/ioctl-siocgifconf.c | 59 ++++++++++++++++++++++------------ libc/calls/ioctl.h | 6 ++++ libc/sock/internal.h | 2 ++ libc/sock/sock.h | 10 ++++-- 4 files changed, 54 insertions(+), 23 deletions(-) diff --git a/libc/calls/ioctl-siocgifconf.c b/libc/calls/ioctl-siocgifconf.c index a862e6029..131ecf373 100644 --- a/libc/calls/ioctl-siocgifconf.c +++ b/libc/calls/ioctl-siocgifconf.c @@ -32,7 +32,10 @@ * 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; int ioctl_siocgifconf_nt(int, struct ifconf *) hidden; +int ioctl_siocgifaddr_nt(int, struct ifconf *) hidden; static int ioctl_siocgifconf_sysv(int fd, struct ifconf *ifc) { if (IsBsd()) { @@ -93,13 +96,16 @@ static int ioctl_siocgifconf_sysv(int fd, struct ifconf *ifc) { } } -static int ioctl_siocgifaddr_sysv(int fd, struct ifreq *ifr) { +/* Used for all the ioctl that returns sockaddr structure that + * requires adjustment between Linux and BSD + */ +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, SIOCGIFADDR, ifr)) < 0) { + if ((i = sys_ioctl(fd, op, ifr)) < 0) { return -1; } if (IsBsd()) { @@ -108,21 +114,6 @@ static int ioctl_siocgifaddr_sysv(int fd, struct ifreq *ifr) { return 0; } -static int ioctl_siocgifnetmask_sysv(int fd, struct ifreq *ifr) { - int i; - - if (IsBsd()) { - sockaddr2bsd(&ifr->ifr_netmask); - } - if ((i = sys_ioctl(fd, SIOCGIFNETMASK, ifr)) < 0) { - return -1; - } - if (IsBsd()) { - sockaddr2linux(&ifr->ifr_netmask); - } - return 0; -} - /** * Returns information about network interfaces. * @@ -139,7 +130,7 @@ int ioctl_siocgifconf(int fd, void *ifc) { int ioctl_siocgifaddr(int fd, void *ifr) { if (!IsWindows()) { - return ioctl_siocgifaddr_sysv(fd, (struct ifreq *)ifr); + return ioctl_siocgifaddr_sysv(fd, SIOCGIFADDR, (struct ifreq *)ifr); } else { return enotsup(); //return ioctl_siocgifaddr_nt(fd, ifc); @@ -148,9 +139,37 @@ int ioctl_siocgifaddr(int fd, void *ifr) { int ioctl_siocgifnetmask(int fd, void *ifr) { if (!IsWindows()) { - return ioctl_siocgifnetmask_sysv(fd, (struct ifreq *)ifr); + return ioctl_siocgifaddr_sysv(fd, SIOCGIFNETMASK, (struct ifreq *)ifr); } else { return enotsup(); - //return ioctl_siocgifaddr_nt(fd, ifc); + //return ioctl_siocgifnetmask_nt(fd, ifc); + } +} + +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); + } +} + +int ioctl_siocgifdstaddr(int fd, void *ifr) { + if (!IsWindows()) { + return ioctl_siocgifaddr_sysv(fd, SIOCGIFDSTADDR, (struct ifreq *)ifr); + } else { + return enotsup(); + //return ioctl_siocgifbrdaddr_nt(fd, ifc); + } +} + +int ioctl_siocgifflags(int fd, void *ifr) { + if (!IsWindows()) { + /* Both BSD and Linux are for once compatible here... */ + return ioctl_default(fd, SIOCGIFFLAGS, ifr); + } else { + return enotsup(); + //return ioctl_siocgifflags_nt(fd, ifc); } } diff --git a/libc/calls/ioctl.h b/libc/calls/ioctl.h index b673f852f..81497bfab 100644 --- a/libc/calls/ioctl.h +++ b/libc/calls/ioctl.h @@ -31,6 +31,9 @@ int ioctl(int, uint64_t, void *); if (CMP(request, SIOCGIFCONF)) return ioctl_siocgifconf(FD, MEMORY); \ if (CMP(request, SIOCGIFADDR)) return ioctl_siocgifaddr(FD, MEMORY); \ if (CMP(request, SIOCGIFNETMASK)) return ioctl_siocgifnetmask(FD, MEMORY); \ + if (CMP(request, SIOCGIFBRDADDR)) return ioctl_siocgifbrdaddr(FD, MEMORY); \ + if (CMP(request, SIOCGIFDSTADDR)) return ioctl_siocgifdstaddr(FD, MEMORY); \ + if (CMP(request, SIOCGIFFLAGS)) return ioctl_siocgifflags(FD, MEMORY); \ } while (0) /* @@ -47,7 +50,10 @@ int ioctl_tiocswinsz(int, void *); int ioctl_tiocswinsz_nt(int, void *); int ioctl_siocgifconf(int, void *); int ioctl_siocgifaddr(int, void *); +int ioctl_siocgifdstaddr(int, void *); int ioctl_siocgifnetmask(int, void *); +int ioctl_siocgifbrdaddr(int, void *); +int ioctl_siocgifflags(int, void *); int ioctl_default(int, uint64_t, void *); forceinline int ioctl_dispatch(int fd, uint64_t request, void *memory) { diff --git a/libc/sock/internal.h b/libc/sock/internal.h index 5ebf63235..d19bf1c88 100644 --- a/libc/sock/internal.h +++ b/libc/sock/internal.h @@ -71,6 +71,8 @@ struct ifreq_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; diff --git a/libc/sock/sock.h b/libc/sock/sock.h index dd2ee4964..fbc873fc1 100644 --- a/libc/sock/sock.h +++ b/libc/sock/sock.h @@ -108,9 +108,11 @@ struct ifreq { } ifr_ifrn; union { - struct sockaddr ifru_addr; - struct sockaddr ifru_netmask; - short ifru_flags; + struct sockaddr ifru_addr; /* SIOCGIFADDR */ + struct sockaddr ifru_dstaddr; /* SIOCGIFDSTADDR */ + struct sockaddr ifru_netmask; /* SIOCGIFNETMASK */ + struct sockaddr ifru_broadaddr; /* SIOCGIFBRDADDR */ + short ifru_flags; /* SIOCGIFFLAGS */ char ifru_pad[24]; /* ifru_map is the largest, just pad */ } ifr_ifru; }; @@ -118,6 +120,8 @@ struct ifreq { #define ifr_name ifr_ifrn.ifrn_name /* interface name */ #define ifr_addr ifr_ifru.ifru_addr /* address */ #define ifr_netmask ifr_ifru.ifru_netmask /* netmask */ +#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ +#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* destination address */ #define ifr_flags ifr_ifru.ifru_flags /* flags */ #define _IOT_ifreq _IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0)