summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog76
-rw-r--r--winsup/cygwin/autoload.cc2
-rw-r--r--winsup/cygwin/cygwin.din4
-rw-r--r--winsup/cygwin/fhandler_procnet.cc211
-rw-r--r--winsup/cygwin/fhandler_socket.cc159
-rw-r--r--winsup/cygwin/include/asm/socket.h1
-rw-r--r--winsup/cygwin/include/cygwin/if.h94
-rw-r--r--winsup/cygwin/include/cygwin/version.h7
-rw-r--r--winsup/cygwin/net.cc503
-rw-r--r--winsup/cygwin/wincap.cc42
10 files changed, 813 insertions, 286 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 02690d2e1..19e0298fa 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,79 @@
+2007-01-21 Corinna Vinschen <corinna@vinschen.de>
+
+ * autoload.cc (WSAIoctl): Define.
+ (SendARP): Define.
+ * cygwin.din: Export if_freenameindex, if_indextoname, if_nameindex and
+ if_nametoindex.
+ * fhandler_procnet.cc: Drop including wchar.h. Drop definitions of
+ GAA_FLAG_INCLUDE_ALL_INTERFACES, IP_ADAPTER_UNICAST_ADDRESS_VISTA.
+ (fhandler_procnet::exists): Check for has_gaa_prefixes. Call
+ get_adapters_addresses here.
+ (fhandler_procnet::readdir): Ditto.
+ (prefix): Move to net.cc.
+ (fhandler_procnet::fill_filebuf): Call get_adapters_addresses here.
+ Simplify allocation. Use AdapterName rather than FriendlyName as
+ interface name. Use IfIndex if available, Ipv6IfIndex otherwise.
+ (in6_are_prefix_equal): Move to net.cc.
+ * fhandler_socket.cc: Define old SIOCGxxx values.
+ (CONV_OLD_TO_NEW_SIO): Convert old SIOCGxxx value to new one.
+ (struct __old_ifreq): Define old struct ifreq.
+ (fhandler_socket::ioctl): Handle old SIOCGxxx values. Handle new
+ SIOCGIFFRNDLYNAM command. Simplify copying ifreq data to user space.
+ Call get_ifconf with additional SOCKET parameter.
+ * net.cc (IP_ADAPTER_UNICAST_ADDRESS_LH): Define.
+ (IP_ADAPTER_ADDRESSES_LH): Define.
+ (SIO_GET_INTERFACE_LIST): Define.
+ (sockaddr_in6_old): Define.
+ (sockaddr_gen): Define.
+ (INTERFACE_INFO): Define.
+ (IN_LOOPBACK): Define.
+ (in_are_prefix_equal): New static function.
+ (ip_addr_prefix): New function, replaces prefix function, add AF_INET
+ handling.
+ (GAA_FLAG_INCLUDE_ALL_INTERFACES): Define.
+ (get_adapters_addresses): New function.
+ (WS_IFF_xxx): Define Winsock interface flag values.
+ (convert_ifr_flags): New function to convert Winsock interface flag
+ values to Cygwin interface flag values.
+ (get_xp_ifconf): New get_ifconf implementation for XP SP1 and above.
+ (get_2k_ifconf): Fix interface index. Fix formatting.
+ (get_nt_ifconf): Fix formatting.
+ (get_95_ifconf): Ditto.
+ (get_ifconf): Take additional SOCKET parameter. Call get_xp_ifconf
+ on XP SP1 and above.
+ (if_nametoindex): New function.
+ (if_indextoname): New function.
+ (if_nameindex): New function.
+ (if_freenameindex): New function.
+ (in6_are_prefix_equal): Moved here from fhandler_procnet.cc.
+ * wincap.cc (wincap_xp): Define has_gaa_prefixes as true by default.
+ (wincapc::init): Assume has_osversioninfoex by default. Call
+ GetVersionEx with OSVERSIONINFOEX first. Call with OSVERSIONINFO only
+ if that fails. Simplify NT4 case and try to avoid strcmp. Check XP
+ Service Pack using version.wServicePackMajor to avoid strcmp.
+ * include/asm/socket.h (SIOCGIFFRNDLYNAM): Define.
+ * include/cygwin/if.h: Fix formatting.
+ (IFF_POINTTOPOINT): Define.
+ (IFF_NOARP): Define.
+ (IFF_LOWER_UP): Define.
+ (IFF_DORMANT): Define.
+ (struct if_nameindex): Define.
+ (IFRF_FRIENDLYNAMESIZ): Define.
+ (struct ifreq_frndlyname): Define.
+ (IFNAMSIZ): Redefine as 44.
+ (IF_NAMESIZE): Define.
+ (struct ifreq): Redefine ifru_flags as int. Define ifru_data. Pad size
+ to sizeof sockaddr_in6 for further extensions.
+ (ifr_data): Define.
+ (ifr_frndlyname): Define.
+ (if_nametoindex): Declare.
+ (if_indextoname): Declare.
+ (if_nameindex): Declare.
+ (if_freenameindex): Declare.
+ * include/cygwin/version.h: Bump API minor number.
+ (CYGWIN_VERSION_CHECK_FOR_OLD_IFREQ): Define check for old vs. new
+ ifreq structure.
+
2007-01-18 Corinna Vinschen <corinna@vinschen.de>
* spawn.cc (spawn_guts): Don't set cwd for non-Cygwin child processes
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index bd8e73371..78974f373 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -487,6 +487,7 @@ LoadDLLfunc (WSACloseEvent, 4, ws2_32)
LoadDLLfunc (WSACreateEvent, 0, ws2_32)
LoadDLLfunc (WSAEnumNetworkEvents, 12, ws2_32)
LoadDLLfunc (WSAEventSelect, 12, ws2_32)
+LoadDLLfunc (WSAIoctl, 36, ws2_32)
LoadDLLfunc (WSAGetLastError, 0, ws2_32)
LoadDLLfunc (WSARecvFrom, 36, ws2_32)
LoadDLLfunc (WSASendTo, 36, ws2_32)
@@ -500,6 +501,7 @@ LoadDLLfuncEx2 (GetIfEntry, 4, iphlpapi, 1, 50)
LoadDLLfuncEx2 (GetIpAddrTable, 12, iphlpapi, 1, 50)
LoadDLLfuncEx2 (GetNetworkParams, 8, iphlpapi, 1, 50)
LoadDLLfuncEx2 (GetTcpTable, 12, iphlpapi, 1, 50)
+LoadDLLfuncEx2 (SendARP, 16, iphlpapi, 1, 50)
LoadDLLfunc (CoTaskMemFree, 4, ole32)
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index c47fd46c8..37e38dcf5 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -699,6 +699,10 @@ hypot NOSIGFE
_hypot = hypot NOSIGFE
hypotf NOSIGFE
_hypotf = hypotf NOSIGFE
+if_freenameindex SIGFE
+if_indextoname SIGFE
+if_nameindex SIGFE
+if_nametoindex SIGFE
ilogb NOSIGFE
_ilogb = ilogb NOSIGFE
ilogbf NOSIGFE
diff --git a/winsup/cygwin/fhandler_procnet.cc b/winsup/cygwin/fhandler_procnet.cc
index 28fc2b2bf..8201a0d1d 100644
--- a/winsup/cygwin/fhandler_procnet.cc
+++ b/winsup/cygwin/fhandler_procnet.cc
@@ -29,11 +29,10 @@ details. */
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
-#include <wchar.h>
-#ifndef GAA_FLAG_INCLUDE_ALL_INTERFACES
-#define GAA_FLAG_INCLUDE_ALL_INTERFACES 0x0100
-#endif
+extern "C" int ip_addr_prefix (PIP_ADAPTER_UNICAST_ADDRESS pua,
+ PIP_ADAPTER_PREFIX pap);
+bool get_adapters_addresses (PIP_ADAPTER_ADDRESSES *pa0, ULONG family);
static const int PROCNET_IFINET6 = 2;
@@ -70,12 +69,8 @@ fhandler_procnet::exists ()
{
if (i == PROCNET_IFINET6)
{
- ULONG size;
- if (GetAdaptersAddresses (AF_INET6,
- GAA_FLAG_INCLUDE_PREFIX
- | GAA_FLAG_INCLUDE_ALL_INTERFACES,
- NULL, NULL, &size)
- != ERROR_BUFFER_OVERFLOW)
+ if (!wincap.has_gaa_prefixes ()
+ || !get_adapters_addresses (NULL, AF_INET6))
return 0;
}
fileid = i;
@@ -129,12 +124,8 @@ fhandler_procnet::readdir (DIR *dir, dirent *de)
goto out;
if (dir->__d_position == PROCNET_IFINET6)
{
- ULONG size;
- if (GetAdaptersAddresses (AF_INET6,
- GAA_FLAG_INCLUDE_PREFIX
- | GAA_FLAG_INCLUDE_ALL_INTERFACES,
- NULL, NULL, &size)
- != ERROR_BUFFER_OVERFLOW)
+ if (!wincap.has_gaa_prefixes ()
+ || !get_adapters_addresses (NULL, AF_INET6))
goto out;
}
strcpy (de->d_name, process_listing[dir->__d_position++]);
@@ -247,92 +238,30 @@ fhandler_procnet::fill_filebuf ()
return true;
}
-static int in6_are_prefix_equal(struct in6_addr *, struct in6_addr *, int);
-
-/* Vista: unicast address has additional OnLinkPrefixLength member. */
-typedef struct _IP_ADAPTER_UNICAST_ADDRESS_VISTA {
- _ANONYMOUS_UNION union {
- ULONGLONG Alignment;
- _ANONYMOUS_UNION struct {
- ULONG Length;
- DWORD Flags;
- } DUMMYSTRUCTNAME;
- } DUMMYUNIONNAME;
- struct _IP_ADAPTER_UNICAST_ADDRESS_VISTA *Next;
- SOCKET_ADDRESS Address;
-
- IP_PREFIX_ORIGIN PrefixOrigin;
- IP_SUFFIX_ORIGIN SuffixOrigin;
- IP_DAD_STATE DadState;
-
- ULONG ValidLifetime;
- ULONG PreferredLifetime;
- ULONG LeaseLifetime;
- unsigned char OnLinkPrefixLength;
-} IP_ADAPTER_UNICAST_ADDRESS_VISTA, *PIP_ADAPTER_UNICAST_ADDRESS_VISTA;
-
-int
-prefix (PIP_ADAPTER_UNICAST_ADDRESS pua, PIP_ADAPTER_PREFIX pap)
-{
- if (wincap.has_gaa_on_link_prefix ())
- return (int) ((PIP_ADAPTER_UNICAST_ADDRESS_VISTA) pua)->OnLinkPrefixLength;
- /* Prior to Vista, the loopback prefix is erroneously set to 0 instead
- of to 128. So just fake it here... */
- if (IN6_IS_ADDR_LOOPBACK (&((struct sockaddr_in6 *)
- pua->Address.lpSockaddr)->sin6_addr))
- return 128;
- /* XP prior to service pack 1 has no prefixes linked list. Let's fake. */
- if (!wincap.has_gaa_prefixes ())
- return 64;
- for ( ; pap; pap = pap->Next)
- if (in6_are_prefix_equal (
- &((struct sockaddr_in6 *) pua->Address.lpSockaddr)->sin6_addr,
- &((struct sockaddr_in6 *) pap->Address.lpSockaddr)->sin6_addr,
- pap->PrefixLength))
- return pap->PrefixLength;
- return 0;
-}
-
static _off64_t
format_procnet_ifinet6 (char *&filebuf)
{
PIP_ADAPTER_ADDRESSES pa0 = NULL, pap;
PIP_ADAPTER_UNICAST_ADDRESS pua;
- ULONG ret, size = 0, alloclen;
+ ULONG alloclen;
+ if (!wincap.has_gaa_prefixes ())
+ return 0;
_off64_t filesize = 0;
- do
- {
- ret = GetAdaptersAddresses (AF_INET6, GAA_FLAG_INCLUDE_PREFIX
- | GAA_FLAG_INCLUDE_ALL_INTERFACES,
- NULL, pa0, &size);
- if (ret == ERROR_BUFFER_OVERFLOW)
- {
- if (pa0)
- free (pa0);
- pa0 = (PIP_ADAPTER_ADDRESSES) malloc (size);
- }
- }
- while (ret == ERROR_BUFFER_OVERFLOW);
- if (ret != ERROR_SUCCESS)
- {
- if (pa0)
- free (pa0);
- return 0;
- }
+ if (!get_adapters_addresses (&pa0, AF_INET6))
+ goto out;
alloclen = 0;
for (pap = pa0; pap; pap = pap->Next)
- {
- ULONG namelen = wcslen (pap->FriendlyName);
- for (pua = pap->FirstUnicastAddress; pua; pua = pua->Next)
- alloclen += 60 + namelen;
- }
+ for (pua = pap->FirstUnicastAddress; pua; pua = pua->Next)
+ alloclen += 100;
+ if (!alloclen)
+ goto out;
filebuf = (char *) crealloc (filebuf, alloclen);
- filesize = 0;
+ if (!filebuf)
+ goto out;
for (pap = pa0; pap; pap = pap->Next)
for (pua = pap->FirstUnicastAddress; pua; pua = pua->Next)
{
- ULONG namelen = wcslen (pap->FriendlyName);
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)
pua->Address.lpSockaddr;
for (int i = 0; i < 8; ++i)
@@ -341,103 +270,17 @@ format_procnet_ifinet6 (char *&filebuf)
ntohs (sin6->sin6_addr.s6_addr16[i]));
filebuf[filesize++] = ' ';
filesize += __small_sprintf (filebuf + filesize,
- "%02x %02x %02x %02x ",
- pap->Ipv6IfIndex,
- prefix (pua, pap->FirstPrefix),
+ "%02x %02x %02x %02x %s\n",
+ pap->IfIndex ?: pap->Ipv6IfIndex,
+ ip_addr_prefix (pua, pap->FirstPrefix),
((struct sockaddr_in6 *)
pua->Address.lpSockaddr)->sin6_scope_id,
- pua->DadState);
- filesize += sys_wcstombs (filebuf + filesize, alloclen - filesize,
- pap->FriendlyName, namelen);
- filebuf[filesize++] = '\n';
+ pua->DadState,
+ pap->AdapterName);
}
- if (!filesize)
- filebuf[filesize++] = '\n';
- return filesize;
-}
-/* The below function has been taken from OpenBSD's src/sys/netinet6/in6.c. */
-
-/*
- * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the project nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * Copyright (c) 1982, 1986, 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)in.c 8.2 (Berkeley) 11/15/93
- */
-
-static int
-in6_are_prefix_equal(struct in6_addr *p1, struct in6_addr *p2, int len)
-{
- int bytelen, bitlen;
-
- /* sanity check */
- if (0 > len || len > 128)
- return 0;
-
- bytelen = len / 8;
- bitlen = len % 8;
-
- if (memcmp (&p1->s6_addr, &p2->s6_addr, bytelen))
- return 0;
- /* len == 128 is ok because bitlen == 0 then */
- if (bitlen != 0 &&
- p1->s6_addr[bytelen] >> (8 - bitlen) !=
- p2->s6_addr[bytelen] >> (8 - bitlen))
- return 0;
-
- return 1;
+out:
+ if (pa0)
+ free (pa0);
+ return filesize;
}
-
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 0ef0f593d..1dadb9604 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -1391,13 +1391,43 @@ fhandler_socket::close ()
return res;
}
+/* Definitions of old ifreq stuff used prior to Cygwin 1.7.0. */
+#define OLD_SIOCGIFFLAGS _IOW('s', 101, struct __old_ifreq)
+#define OLD_SIOCGIFADDR _IOW('s', 102, struct __old_ifreq)
+#define OLD_SIOCGIFBRDADDR _IOW('s', 103, struct __old_ifreq)
+#define OLD_SIOCGIFNETMASK _IOW('s', 104, struct __old_ifreq)
+#define OLD_SIOCGIFHWADDR _IOW('s', 105, struct __old_ifreq)
+#define OLD_SIOCGIFMETRIC _IOW('s', 106, struct __old_ifreq)
+#define OLD_SIOCGIFMTU _IOW('s', 107, struct __old_ifreq)
+#define OLD_SIOCGIFINDEX _IOW('s', 108, struct __old_ifreq)
+
+#define CONV_OLD_TO_NEW_SIO(old) (((old)&0xff00ffff)|(((long)sizeof(struct ifreq)&IOCPARM_MASK)<<16))
+
+struct __old_ifreq {
+#define __OLD_IFNAMSIZ 16
+ union {
+ char ifrn_name[__OLD_IFNAMSIZ]; /* if name, e.g. "en0" */
+ } ifr_ifrn;
+
+ union {
+ struct sockaddr ifru_addr;
+ struct sockaddr ifru_broadaddr;
+ struct sockaddr ifru_netmask;
+ struct sockaddr ifru_hwaddr;
+ short ifru_flags;
+ int ifru_metric;
+ int ifru_mtu;
+ int ifru_ifindex;
+ } ifr_ifru;
+};
+
int
fhandler_socket::ioctl (unsigned int cmd, void *p)
{
- extern int get_ifconf (struct ifconf *ifc, int what); /* net.cc */
+ extern int get_ifconf (SOCKET s, struct ifconf *ifc, int what); /* net.cc */
int res;
struct ifconf ifc, *ifcp;
- struct ifreq *ifr, *ifrp;
+ struct ifreq *ifrp;
switch (cmd)
{
@@ -1408,10 +1438,47 @@ fhandler_socket::ioctl (unsigned int cmd, void *p)
set_errno (EINVAL);
return -1;
}
- res = get_ifconf (ifcp, cmd);
+ if (CYGWIN_VERSION_CHECK_FOR_OLD_IFREQ)
+ {
+ ifc.ifc_len = ifcp->ifc_len / sizeof (struct __old_ifreq)
+ * sizeof (struct ifreq);
+ ifc.ifc_buf = (caddr_t) alloca (ifc.ifc_len);
+ }
+ else
+ {
+ ifc.ifc_len = ifcp->ifc_len;
+ ifc.ifc_buf = ifcp->ifc_buf;
+ }
+ res = get_ifconf (get_socket (), &ifc, cmd);
if (res)
debug_printf ("error in get_ifconf");
+ if (CYGWIN_VERSION_CHECK_FOR_OLD_IFREQ)
+ {
+ struct __old_ifreq *ifr = (struct __old_ifreq *) ifcp->ifc_buf;
+ for (ifrp = ifc.ifc_req;
+ (caddr_t) ifrp < ifc.ifc_buf + ifc.ifc_len;
+ ++ifrp, ++ifr)
+ {
+ memcpy (&ifr->ifr_ifrn, &ifrp->ifr_ifrn, sizeof ifr->ifr_ifrn);
+ ifr->ifr_name[__OLD_IFNAMSIZ - 1] = '\0';
+ memcpy (&ifr->ifr_ifru, &ifrp->ifr_ifru, sizeof ifr->ifr_ifru);
+ }
+ ifcp->ifc_len = ifc.ifc_len / sizeof (struct ifreq)
+ * sizeof (struct __old_ifreq);
+ }
+ else
+ ifcp->ifc_len = ifc.ifc_len;
break;
+ case OLD_SIOCGIFFLAGS:
+ case OLD_SIOCGIFADDR:
+ case OLD_SIOCGIFBRDADDR:
+ case OLD_SIOCGIFNETMASK:
+ case OLD_SIOCGIFHWADDR:
+ case OLD_SIOCGIFMETRIC:
+ case OLD_SIOCGIFMTU:
+ case OLD_SIOCGIFINDEX:
+ cmd = CONV_OLD_TO_NEW_SIO (cmd);
+ /*FALLTHRU*/
case SIOCGIFFLAGS:
case SIOCGIFBRDADDR:
case SIOCGIFNETMASK:
@@ -1420,61 +1487,75 @@ fhandler_socket::ioctl (unsigned int cmd, void *p)
case SIOCGIFMETRIC:
case SIOCGIFMTU:
case SIOCGIFINDEX:
+ case SIOCGIFFRNDLYNAM:
{
- ifc.ifc_len = 2048;
- ifc.ifc_buf = (char *) alloca (2048);
-
- ifr = (struct ifreq *) p;
- if (ifr == 0)
+ if (!p)
{
debug_printf ("ifr == NULL");
set_errno (EINVAL);
return -1;
}
- res = get_ifconf (&ifc, cmd);
+ if (cmd > SIOCGIFINDEX && CYGWIN_VERSION_CHECK_FOR_OLD_IFREQ)
+ {
+ debug_printf ("cmd not supported on this platform");
+ set_errno (EINVAL);
+ return -1;
+ }
+ ifc.ifc_len = 64 * sizeof (struct ifreq);
+ ifc.ifc_buf = (caddr_t) alloca (ifc.ifc_len);
+ if (cmd == SIOCGIFFRNDLYNAM)
+ {
+ struct ifreq_frndlyname *iff = (struct ifreq_frndlyname *)
+ alloca (64 * sizeof (struct ifreq_frndlyname));
+ for (int i = 0; i < 64; ++i)
+ ifc.ifc_req[i].ifr_frndlyname = &iff[i];
+ }
+
+ res = get_ifconf (get_socket (), &ifc, cmd);
if (res)
{
debug_printf ("error in get_ifconf");
break;
}
- debug_printf (" name: %s", ifr->ifr_name);
- for (ifrp = ifc.ifc_req;
- (caddr_t) ifrp < ifc.ifc_buf + ifc.ifc_len;
- ++ifrp)
+ if (CYGWIN_VERSION_CHECK_FOR_OLD_IFREQ)
{
- debug_printf ("testname: %s", ifrp->ifr_name);
- if (! strcmp (ifrp->ifr_name, ifr->ifr_name))
+ struct __old_ifreq *ifr = (struct __old_ifreq *) p;
+ debug_printf (" name: %s", ifr->ifr_name);
+ for (ifrp = ifc.ifc_req;
+ (caddr_t) ifrp < ifc.ifc_buf + ifc.ifc_len;
+ ++ifrp)
{
- switch (cmd)
+ debug_printf ("testname: %s", ifrp->ifr_name);
+ if (! strcmp (ifrp->ifr_name, ifr->ifr_name))
{
- case SIOCGIFFLAGS:
- ifr->ifr_flags = ifrp->ifr_flags;
- break;
- case SIOCGIFADDR:
- ifr->ifr_addr = ifrp->ifr_addr;
- break;
- case SIOCGIFBRDADDR:
- ifr->ifr_broadaddr = ifrp->ifr_broadaddr;
- break;
- case SIOCGIFNETMASK:
- ifr->ifr_netmask = ifrp->ifr_netmask;
- break;
- case SIOCGIFHWADDR:
- ifr->ifr_hwaddr = ifrp->ifr_hwaddr;
- break;
- case SIOCGIFMETRIC:
- ifr->ifr_metric = ifrp->ifr_metric;
+ memcpy (&ifr->ifr_ifru, &ifrp->ifr_ifru,
+ sizeof ifr->ifr_ifru);
break;
- case SIOCGIFMTU:
- ifr->ifr_mtu = ifrp->ifr_mtu;
- break;
- case SIOCGIFINDEX:
- ifr->ifr_ifindex = ifrp->ifr_ifindex;
+ }
+ }
+ }
+ else
+ {
+ struct ifreq *ifr = (struct ifreq *) p;
+ debug_printf (" name: %s", ifr->ifr_name);
+ for (ifrp = ifc.ifc_req;
+ (caddr_t) ifrp < ifc.ifc_buf + ifc.ifc_len;
+ ++ifrp)
+ {
+ debug_printf ("testname: %s", ifrp->ifr_name);
+ if (! strcmp (ifrp->ifr_name, ifr->ifr_name))
+ {
+ if (cmd == SIOCGIFFRNDLYNAM)
+ /* The application has to care for the space. */
+ memcpy (ifr->ifr_frndlyname, ifrp->ifr_frndlyname,
+ sizeof (struct ifreq_frndlyname));
+ else
+ memcpy (&ifr->ifr_ifru, &ifrp->ifr_ifru,
+ sizeof ifr->ifr_ifru);
break;
}
- break;
}
}
if ((caddr_t) ifrp >= ifc.ifc_buf + ifc.ifc_len)
diff --git a/winsup/cygwin/include/asm/socket.h b/winsup/cygwin/include/asm/socket.h
index 4541bc850..f8e93cc81 100644
--- a/winsup/cygwin/include/asm/socket.h
+++ b/winsup/cygwin/include/asm/socket.h
@@ -43,6 +43,7 @@ details. */
#define SIOCGIFMTU _IOW('s', 107, struct ifreq) /* get MTU size */
#define SIOCGIFINDEX _IOW('s', 108, struct ifreq) /* get if index */
#define SIOGIFINDEX SIOCGIFINDEX /* backward compatibility w/ Linux typo. */
+#define SIOCGIFFRNDLYNAM _IOW('s', 109, struct ifreq) /* get friendly if name */
#define SOL_SOCKET 0xffff /* options for socket level */
diff --git a/winsup/cygwin/include/cygwin/if.h b/winsup/cygwin/include/cygwin/if.h
index fe36afcf2..c61e2ada2 100644
--- a/winsup/cygwin/include/cygwin/if.h
+++ b/winsup/cygwin/include/cygwin/if.h
@@ -19,13 +19,32 @@ extern "C" {
#include <sys/socket.h>
/* Standard interface flags. */
-#define IFF_UP 0x1 /* interface is up */
-#define IFF_BROADCAST 0x2 /* broadcast address valid */
-#define IFF_LOOPBACK 0x8 /* is a loopback net */
-#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */
-#define IFF_RUNNING 0x40 /* resources allocated */
-#define IFF_PROMISC 0x100 /* receive all packets */
-#define IFF_MULTICAST 0x1000 /* Supports multicast */
+#define IFF_UP 0x1 /* interface is up */
+#define IFF_BROADCAST 0x2 /* broadcast address valid */
+#define IFF_LOOPBACK 0x8 /* is a loopback net */
+#define IFF_POINTTOPOINT 0x10 /* is a point-to-point interface */
+#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */
+#define IFF_RUNNING 0x40 /* resources allocated */
+#define IFF_NOARP 0x80 /* no ARP protocol */
+#define IFF_PROMISC 0x100 /* receive all packets */
+#define IFF_MULTICAST 0x1000 /* Supports multicast */
+#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */
+#define IFF_DORMANT 0x20000 /* driver signals dormant */
+
+struct if_nameindex {
+ unsigned if_index;
+ char *if_name;
+};
+
+/* This is the structure expected by ioctl when the application requests
+ the friendly adapter name (>= XP SP1). ifru_data should point to such
+ a structure when ioctl is called with SIOCGIFFRNDLYNAM. */
+#define IFRF_FRIENDLYNAMESIZ 260
+
+struct ifreq_frndlyname {
+ int ifrf_len;
+ char ifrf_friendlyname[IFRF_FRIENDLYNAMESIZ];
+};
/*
* Interface request structure used for socket
@@ -33,26 +52,29 @@ extern "C" {
* definitions which begin with ifr_name. The
* remainder may be interface specific.
*/
-
-struct ifreq
-{
-#define IFNAMSIZ 16
+#define IFNAMSIZ 44
+#define IF_NAMESIZE IFNAMSIZ
#define IFHWADDRLEN 6
- union
- {
- char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */
- } ifr_ifrn;
-
- union {
- struct sockaddr ifru_addr;
- struct sockaddr ifru_broadaddr;
- struct sockaddr ifru_netmask;
- struct sockaddr ifru_hwaddr;
- short ifru_flags;
- int ifru_metric;
- int ifru_mtu;
- int ifru_ifindex;
- } ifr_ifru;
+
+struct ifreq {
+ union {
+ char ifrn_name[IFNAMSIZ]; /* Unique Windows Adapter name (A GUID) */
+ } ifr_ifrn;
+
+ union {
+ struct sockaddr ifru_addr;
+ struct sockaddr ifru_broadaddr;
+ struct sockaddr ifru_netmask;
+ struct sockaddr ifru_hwaddr;
+ int ifru_flags;
+ int ifru_metric;
+ int ifru_mtu;
+ int ifru_ifindex;
+ /* The space must be preallocated by the application. */
+ void *ifru_data;
+ /* Pad to sizeof sockaddr_in6 for further extensions. */
+ char __ifru_pad[28];
+ } ifr_ifru;
};
#define ifr_name ifr_ifrn.ifrn_name /* interface name */
@@ -64,6 +86,8 @@ struct ifreq
#define ifr_metric ifr_ifru.ifru_metric /* metric */
#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
#define ifr_ifindex ifr_ifru.ifru_ifindex /* interface index */
+#define ifr_data ifr_ifru.ifru_data /* for use by interface */
+#define ifr_frndlyname ifr_ifru.ifru_data /* Windows friendly if name */
/*
* Structure used in SIOCGIFCONF request.
@@ -74,16 +98,22 @@ struct ifreq
struct ifconf
{
- int ifc_len; /* size of buffer */
- union
- {
- caddr_t ifcu_buf;
- struct ifreq *ifcu_req;
- } ifc_ifcu;
+ int ifc_len; /* size of buffer */
+ union
+ {
+ caddr_t ifcu_buf;
+ struct ifreq *ifcu_req;
+ } ifc_ifcu;
};
+
#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */
#define ifc_req ifc_ifcu.ifcu_req /* array of structures */
+extern unsigned if_nametoindex (const char *);
+extern char *if_indextoname (unsigned, char *);
+extern struct if_nameindex *if_nameindex (void);
+extern void if_freenameindex (struct if_nameindex *);
+
#ifdef __cplusplus
};
#endif /* __cplusplus */
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index dd448aef2..44c7229c3 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -94,6 +94,9 @@ details. */
#define CYGWIN_VERSION_CHECK_FOR_USING_WINSOCK1_VALUES \
(CYGWIN_VERSION_USER_API_VERSION_COMBINED <= 138)
+#define CYGWIN_VERSION_CHECK_FOR_OLD_IFREQ \
+ (CYGWIN_VERSION_USER_API_VERSION_COMBINED <= 161)
+
/* API_MAJOR 0.0: Initial version. API_MINOR changes:
1: Export cygwin32_ calls as cygwin_ as well.
2: Export j1, jn, y1, yn.
@@ -296,12 +299,14 @@ details. */
159: Export posix_openpt.
160: Export posix_fadvice, posix_fallocate.
161: Export resolver functions.
+ 162: New struct ifreq. Export if_nametoindex, if_indextoname,
+ if_nameindex, if_freenameindex.
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 161
+#define CYGWIN_VERSION_API_MINOR 162
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible
diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc
index 13a1ee9df..c6cf34b60 100644
--- a/winsup/cygwin/net.cc
+++ b/winsup/cygwin/net.cc
@@ -1125,6 +1125,315 @@ getdomainname (char *domain, size_t len)
/* Fill out an ifconf struct. */
+/* Vista/Longhorn: unicast address has additional OnLinkPrefixLength member. */
+typedef struct _IP_ADAPTER_UNICAST_ADDRESS_LH {
+ _ANONYMOUS_UNION union {
+ ULONGLONG Alignment;
+ _ANONYMOUS_UNION struct {
+ ULONG Length;
+ DWORD Flags;
+ } DUMMYSTRUCTNAME;
+ } DUMMYUNIONNAME;
+ struct _IP_ADAPTER_UNICAST_ADDRESS_VISTA *Next;
+ SOCKET_ADDRESS Address;
+ IP_PREFIX_ORIGIN PrefixOrigin;
+ IP_SUFFIX_ORIGIN SuffixOrigin;
+ IP_DAD_STATE DadState;
+ ULONG ValidLifetime;
+ ULONG PreferredLifetime;
+ ULONG LeaseLifetime;
+ unsigned char OnLinkPrefixLength;
+} IP_ADAPTER_UNICAST_ADDRESS_LH, *PIP_ADAPTER_UNICAST_ADDRESS_LH;
+
+/* Vista/Longhorn: IP_ADAPTER_ADDRESSES has a lot more info. We pick only
+ what we need for now. */
+typedef struct _IP_ADAPTER_ADDRESSES_LH {
+ _ANONYMOUS_UNION union {
+ ULONGLONG Alignment;
+ _ANONYMOUS_STRUCT struct {
+ ULONG Length;
+ DWORD IfIndex;
+ } DUMMYSTRUCTNAME;
+ } DUMMYUNIONNAME;
+ struct _IP_ADAPTER_ADDRESSES* Next;
+ PCHAR AdapterName;
+ PIP_ADAPTER_UNICAST_ADDRESS FirstUnicastAddress;
+ PIP_ADAPTER_ANYCAST_ADDRESS FirstAnycastAddress;
+ PIP_ADAPTER_MULTICAST_ADDRESS FirstMulticastAddress;
+ PIP_ADAPTER_DNS_SERVER_ADDRESS FirstDnsServerAddress;
+ PWCHAR DnsSuffix;
+ PWCHAR Description;
+ PWCHAR FriendlyName;
+ BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH];
+ DWORD PhysicalAddressLength;
+ DWORD Flags;
+ DWORD Mtu;
+ DWORD IfType;
+ IF_OPER_STATUS OperStatus;
+ DWORD Ipv6IfIndex;
+ DWORD ZoneIndices[16];
+ PIP_ADAPTER_PREFIX FirstPrefix;
+
+ ULONG64 TransmitLinkSpeed;
+ ULONG64 ReceiveLinkSpeed;
+ PVOID FirstWinsServerAddress;
+ PVOID FirstGatewayAddress;
+ ULONG Ipv4Metric;
+ ULONG Ipv6Metric;
+} IP_ADAPTER_ADDRESSES_LH,*PIP_ADAPTER_ADDRESSES_LH;
+
+/* We can't include ws2tcpip.h. */
+
+#define SIO_GET_INTERFACE_LIST _IOR('t', 127, u_long)
+
+struct sockaddr_in6_old {
+ short sin6_family;
+ u_short sin6_port;
+ u_long sin6_flowinfo;
+ struct in6_addr sin6_addr;
+};
+
+typedef union sockaddr_gen{
+ struct sockaddr Address;
+ struct sockaddr_in AddressIn;
+ struct sockaddr_in6_old AddressIn6;
+} sockaddr_gen;
+
+typedef struct _INTERFACE_INFO {
+ u_long iiFlags;
+ sockaddr_gen iiAddress;
+ sockaddr_gen iiBroadcastAddress;
+ sockaddr_gen iiNetmask;
+} INTERFACE_INFO, *LPINTERFACE_INFO;
+
+#ifndef IN_LOOPBACK
+#define IN_LOOPBACK(a) ((((long int) (a)) & 0xff000000) == 0x7f000000)
+#endif
+
+static int in6_are_prefix_equal (struct in6_addr *, struct in6_addr *, int);
+
+static int in_are_prefix_equal (struct in_addr *p1, struct in_addr *p2, int len)
+{
+ if (0 > len || len > 32)
+ return 0;
+ uint32_t pfxmask = 0xffffffff << (32 - len);
+ return (p1->s_addr & pfxmask) == (p2->s_addr & pfxmask);
+}
+
+extern "C" int
+ip_addr_prefix (PIP_ADAPTER_UNICAST_ADDRESS pua, PIP_ADAPTER_PREFIX pap)
+{
+ if (wincap.has_gaa_on_link_prefix ())
+ return (int) ((PIP_ADAPTER_UNICAST_ADDRESS_LH) pua)->OnLinkPrefixLength;
+ switch (pua->Address.lpSockaddr->sa_family)
+ {
+ case AF_INET:
+ /* Prior to Vista, the loopback prefix is not available. */
+ if (IN_LOOPBACK (((struct sockaddr_in *)
+ pua->Address.lpSockaddr)->sin_addr.s_addr))
+ return 8;
+ for ( ; pap; pap = pap->Next)
+ if (in_are_prefix_equal (
+ &((struct sockaddr_in *) pua->Address.lpSockaddr)->sin_addr,
+ &((struct sockaddr_in *) pap->Address.lpSockaddr)->sin_addr,
+ pap->PrefixLength))
+ return pap->PrefixLength;
+ break;
+ case AF_INET6:
+ /* Prior to Vista, the loopback prefix is not available. */
+ if (IN6_IS_ADDR_LOOPBACK (&((struct sockaddr_in6 *)
+ pua->Address.lpSockaddr)->sin6_addr))
+ return 128;
+ for ( ; pap; pap = pap->Next)
+ if (in6_are_prefix_equal (
+ &((struct sockaddr_in6 *) pua->Address.lpSockaddr)->sin6_addr,
+ &((struct sockaddr_in6 *) pap->Address.lpSockaddr)->sin6_addr,
+ pap->PrefixLength))
+ return pap->PrefixLength;
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+#ifndef GAA_FLAG_INCLUDE_ALL_INTERFACES
+#define GAA_FLAG_INCLUDE_ALL_INTERFACES 0x0100
+#endif
+
+bool
+get_adapters_addresses (PIP_ADAPTER_ADDRESSES *pa_ret, ULONG family)
+{
+ DWORD ret, size = 0;
+ PIP_ADAPTER_ADDRESSES pa0 = NULL;
+
+ if (!pa_ret)
+ return ERROR_BUFFER_OVERFLOW
+ == GetAdaptersAddresses (family, GAA_FLAG_INCLUDE_PREFIX
+ | GAA_FLAG_INCLUDE_ALL_INTERFACES,
+ NULL, NULL, &size);
+ do
+ {
+ ret = GetAdaptersAddresses (family, GAA_FLAG_INCLUDE_PREFIX
+ | GAA_FLAG_INCLUDE_ALL_INTERFACES,
+ NULL, pa0, &size);
+ if (ret == ERROR_BUFFER_OVERFLOW
+ && !(pa0 = (PIP_ADAPTER_ADDRESSES) realloc (pa0, size)))
+ break;
+ }
+ while (ret == ERROR_BUFFER_OVERFLOW);
+ if (ret != ERROR_SUCCESS)
+ {
+ if (pa0)
+ free (pa0);
+ *pa_ret = NULL;
+ return false;
+ }
+ *pa_ret = pa0;
+ return true;
+}
+
+#define WS_IFF_UP 1
+#define WS_IFF_BROADCAST 2
+#define WS_IFF_LOOPBACK 4
+#define WS_IFF_POINTTOPOINT 8
+#define WS_IFF_MULTICAST 16
+
+static inline short
+convert_ifr_flags (u_long ws_flags)
+{
+ return (ws_flags & (WS_IFF_UP | WS_IFF_BROADCAST))
+ | ((ws_flags & (WS_IFF_LOOPBACK | WS_IFF_POINTTOPOINT)) << 1)
+ | ((ws_flags & WS_IFF_MULTICAST) << 8);
+}
+
+/*
+ * IFCONF XP SP1 and above.
+ * Use IP Helpper function GetAdaptersAddresses.
+ */
+
+static void
+get_xp_ifconf (SOCKET s, struct ifconf *ifc, int what)
+{
+ PIP_ADAPTER_ADDRESSES pa0 = NULL, pap;
+ PIP_ADAPTER_UNICAST_ADDRESS pua;
+ LPINTERFACE_INFO iie;
+ int cnt = 0;
+ DWORD size = 0;
+
+ if (!get_adapters_addresses (&pa0, AF_INET))
+ goto done;
+
+ for (pap = pa0; pap; pap = pap->Next)
+ for (pua = pap->FirstUnicastAddress; pua; pua = pua->Next)
+ ++cnt;
+ /* If the size matches exactly the number of interfaces, WSAIoctl fails
+ with WSAError set to WSAEFAULT, for no apparent reason. So we allocate
+ space for one more INTERFACE_INFO structure here. */
+ iie = (LPINTERFACE_INFO) alloca ((cnt + 1) * sizeof (INTERFACE_INFO));
+ if (WSAIoctl (s, SIO_GET_INTERFACE_LIST, NULL, 0, iie,
+ (cnt + 1) * sizeof (INTERFACE_INFO), &size, NULL, NULL))
+ {
+ set_winsock_errno ();
+ cnt = 0;
+ goto done;
+ }
+
+ struct ifreq *ifr = ifc->ifc_req;
+ for (pap = pa0; pap; pap = pap->Next)
+ {
+ int idx = 0;
+ for (pua = pap->FirstUnicastAddress; pua; pua = pua->Next)
+ {
+ int iinf_idx;
+ for (iinf_idx = 0; iinf_idx < cnt; ++iinf_idx)
+ if (iie[iinf_idx].iiAddress.AddressIn.sin_addr.s_addr
+ == ((sockaddr_in *) pua->Address.lpSockaddr)->sin_addr.s_addr)
+ break;
+ if (iinf_idx >= cnt)
+ continue;
+ if (!idx)
+ strcpy (ifr->ifr_name, pap->AdapterName);
+ else
+ __small_sprintf (ifr->ifr_name, "%s:%u", pap->AdapterName, idx);
+ ++idx;
+ switch (what)
+ {
+ case SIOCGIFFLAGS:
+ {
+ ifr->ifr_flags = convert_ifr_flags (iie[iinf_idx].iiFlags);
+ if (pap->OperStatus == IfOperStatusUp
+ || pap->OperStatus == IfOperStatusUnknown)
+ ifr->ifr_flags |= IFF_RUNNING;
+ if (pap->OperStatus != IfOperStatusLowerLayerDown)
+ ifr->ifr_flags |= IFF_LOWER_UP;
+ if (pap->OperStatus == IfOperStatusDormant)
+ ifr->ifr_flags |= IFF_DORMANT;
+ ULONG hwaddr[2], hwlen = 6;
+ if (SendARP (iie[iinf_idx].iiAddress.AddressIn.sin_addr.s_addr,
+ 0, hwaddr, &hwlen))
+ ifr->ifr_flags |= IFF_NOARP;
+ }
+ break;
+ case SIOCGIFCONF:
+ case SIOCGIFADDR:
+ memcpy (&ifr->ifr_addr,
+ &iie[iinf_idx].iiAddress.AddressIn,
+ sizeof (struct sockaddr_in));
+ break;
+ case SIOCGIFBRDADDR:
+ memcpy (&ifr->ifr_broadaddr,
+ &iie[iinf_idx].iiBroadcastAddress.AddressIn,
+ sizeof (struct sockaddr_in));
+ break;
+ case SIOCGIFNETMASK:
+ memcpy (&ifr->ifr_netmask,
+ &iie[iinf_idx].iiNetmask.AddressIn,
+ sizeof (struct sockaddr_in));
+ break;
+ case SIOCGIFHWADDR:
+ for (UINT i = 0; i < IFHWADDRLEN; ++i)
+ if (i >= pap->PhysicalAddressLength)
+ ifr->ifr_hwaddr.sa_data[i] = '\0';
+ else
+ ifr->ifr_hwaddr.sa_data[i] = pap->PhysicalAddress[i];
+ ifr->ifr_hwaddr.sa_family = AF_INET;
+ break;
+ case SIOCGIFMETRIC:
+ if (wincap.has_gaa_on_link_prefix ())
+ ifr->ifr_metric = ((PIP_ADAPTER_ADDRESSES_LH) pap)->Ipv4Metric;
+ else
+ ifr->ifr_metric = 1;
+ break;
+ case SIOCGIFMTU:
+ ifr->ifr_mtu = pap->Mtu;
+ break;
+ case SIOCGIFINDEX:
+ ifr->ifr_ifindex = pap->IfIndex;
+ break;
+ case SIOCGIFFRNDLYNAM:
+ {
+ struct ifreq_frndlyname *iff = (struct ifreq_frndlyname *)
+ ifr->ifr_frndlyname;
+ iff->ifrf_len = sys_wcstombs (iff->ifrf_friendlyname,
+ IFRF_FRIENDLYNAMESIZ,
+ pap->FriendlyName);
+ }
+ break;
+ }
+ if ((caddr_t) ++ifr >
+ ifc->ifc_buf + ifc->ifc_len - sizeof (struct ifreq))
+ goto done;
+ }
+ }
+
+done:
+ if (pa0)
+ free (pa0);
+ /* Set the correct length */
+ ifc->ifc_len = cnt * sizeof (struct ifreq);
+}
+
/*
* IFCONF 98/ME, NTSP4, W2K:
* Use IP Helper Library
@@ -1239,7 +1548,7 @@ get_2k_ifconf (struct ifconf *ifc, int what)
__small_sprintf (ifr->ifr_name, "%s%u", name, ifEntry->classId);
else
__small_sprintf (ifr->ifr_name, "%s%u:%u", name,
- ifEntry->classId, ifEntry->enumerated - 1);
+ ifEntry->classId, ifEntry->enumerated);
ifEntry->enumerated++;
}
@@ -1304,7 +1613,7 @@ get_2k_ifconf (struct ifconf *ifc, int what)
break;
}
++cnt;
- if ((caddr_t)++ ifr >
+ if ((caddr_t) ++ifr >
ifc->ifc_buf + ifc->ifc_len - sizeof (struct ifreq))
goto done;
}
@@ -1396,7 +1705,7 @@ get_nt_ifconf (struct ifconf *ifc, int what)
*ip && *np;
ip += strlen (ip) + 1, np += strlen (np) + 1)
{
- if ((caddr_t)++ ifr > ifc->ifc_buf
+ if ((caddr_t) ++ifr > ifc->ifc_buf
+ ifc->ifc_len - sizeof (struct ifreq))
break;
@@ -1606,7 +1915,7 @@ get_95_ifconf (struct ifconf *ifc, int what)
NULL, (unsigned char *) np,
(size = sizeof np, &size)) == ERROR_SUCCESS)
{
- if ((caddr_t)++ ifr > ifc->ifc_buf
+ if ((caddr_t) ++ifr > ifc->ifc_buf
+ ifc->ifc_len - sizeof (struct ifreq))
goto out;
@@ -1697,7 +2006,7 @@ out:
}
int
-get_ifconf (struct ifconf *ifc, int what)
+get_ifconf (SOCKET s, struct ifconf *ifc, int what)
{
unsigned long lip, lnp;
struct sockaddr_in *sa;
@@ -1768,7 +2077,9 @@ get_ifconf (struct ifconf *ifc, int what)
}
}
- if (wincap.has_ip_helper_lib ())
+ if (wincap.has_gaa_prefixes () && !CYGWIN_VERSION_CHECK_FOR_OLD_IFREQ)
+ get_xp_ifconf (s, ifc, what);
+ else if (wincap.has_ip_helper_lib ())
get_2k_ifconf (ifc, what);
else if (wincap.is_winnt ())
get_nt_ifconf (ifc, what);
@@ -1777,6 +2088,102 @@ get_ifconf (struct ifconf *ifc, int what)
return 0;
}
+extern "C" unsigned
+if_nametoindex (const char *name)
+{
+ PIP_ADAPTER_ADDRESSES pap = NULL;
+
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return 0;
+
+ if (wincap.has_gaa_prefixes ()
+ && get_adapters_addresses (&pap, AF_UNSPEC))
+ {
+ char lname[IF_NAMESIZE], *c;
+
+ lname[0] = '\0';
+ strncat (lname, name, IF_NAMESIZE - 1);
+ if (lname[0] == '{' && (c = strchr (lname, ':')))
+ *c = '\0';
+ for (; pap; pap = pap->Next)
+ if (strcasematch (lname, pap->AdapterName))
+ return pap->IfIndex;
+ }
+ return 0;
+}
+
+extern "C" char *
+if_indextoname (unsigned ifindex, char *ifname)
+{
+ PIP_ADAPTER_ADDRESSES pap = NULL;
+
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return NULL;
+
+ if (wincap.has_gaa_prefixes ()
+ && get_adapters_addresses (&pap, AF_UNSPEC))
+ {
+ for (; pap; pap = pap->Next)
+ if (ifindex == pap->IfIndex)
+ {
+ strcpy (ifname, pap->AdapterName);
+ return ifname;
+ }
+ }
+ set_errno (ENXIO);
+ return NULL;
+}
+
+extern "C" struct if_nameindex *
+if_nameindex (void)
+{
+ PIP_ADAPTER_ADDRESSES pa0 = NULL, pap;
+ struct if_nameindex *iflist = NULL;
+ char (*ifnamelist)[IF_NAMESIZE];
+
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return NULL;
+
+ if (wincap.has_gaa_prefixes ()
+ && get_adapters_addresses (&pa0, AF_UNSPEC))
+ {
+ int cnt = 0;
+ for (pap = pa0; pap; pap = pap->Next)
+ ++cnt;
+ iflist = (struct if_nameindex *)
+ malloc ((cnt + 1) * sizeof (struct if_nameindex)
+ + cnt * IF_NAMESIZE);
+ if (!iflist)
+ {
+ set_errno (ENOBUFS);
+ return NULL;
+ }
+ ifnamelist = (char (*)[IF_NAMESIZE]) (iflist + cnt + 1);
+ for (pap = pa0, cnt = 0; pap; pap = pap->Next, ++cnt)
+ {
+ iflist[cnt].if_index = pap->IfIndex ?: pap->Ipv6IfIndex;
+ strcpy (iflist[cnt].if_name = ifnamelist[cnt], pap->AdapterName);
+ }
+ iflist[cnt].if_index = 0;
+ iflist[cnt].if_name = NULL;
+ return iflist;
+ }
+ set_errno (ENXIO);
+ return NULL;
+}
+
+extern "C" void
+if_freenameindex (struct if_nameindex *ptr)
+{
+ myfault efault;
+ if (efault.faulted (EFAULT))
+ return;
+ free (ptr);
+}
+
#define PORT_LOW (IPPORT_EFSSERVER + 1)
#define PORT_HIGH (IPPORT_RESERVED - 1)
#define NUM_PORTS (PORT_HIGH - PORT_LOW + 1)
@@ -3493,3 +3900,87 @@ cygwin_getnameinfo (const struct sockaddr *sa, socklen_t salen,
return ipv4_getnameinfo (sa, salen, host, hostlen, serv, servlen, flags);
}
+/* The below function has been taken from OpenBSD's src/sys/netinet6/in6.c. */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1982, 1986, 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)in.c 8.2 (Berkeley) 11/15/93
+ */
+
+static int
+in6_are_prefix_equal (struct in6_addr *p1, struct in6_addr *p2, int len)
+{
+ int bytelen, bitlen;
+
+ /* sanity check */
+ if (0 > len || len > 128)
+ return 0;
+
+ bytelen = len / 8;
+ bitlen = len % 8;
+
+ if (memcmp (&p1->s6_addr, &p2->s6_addr, bytelen))
+ return 0;
+ /* len == 128 is ok because bitlen == 0 then */
+ if (bitlen != 0 &&
+ p1->s6_addr[bytelen] >> (8 - bitlen) !=
+ p2->s6_addr[bytelen] >> (8 - bitlen))
+ return 0;
+
+ return 1;
+}
diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc
index d9aa59093..7e9f71069 100644
--- a/winsup/cygwin/wincap.cc
+++ b/winsup/cygwin/wincap.cc
@@ -722,7 +722,7 @@ static NO_COPY wincaps wincap_xp = {
needs_logon_sid_in_sid_list:false,
needs_count_in_si_lpres2:false,
has_recycle_dot_bin:false,
- has_gaa_prefixes:false,
+ has_gaa_prefixes:true,
has_gaa_on_link_prefix:false,
};
@@ -862,15 +862,21 @@ void
wincapc::init ()
{
const char *os;
- bool has_osversioninfoex = false;
+ bool has_osversioninfoex = true;
if (caps)
return; // already initialized
memset (&version, 0, sizeof version);
- /* Request simple version info first. */
- version.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
- GetVersionEx (reinterpret_cast<LPOSVERSIONINFO>(&version));
+ /* Request versionex info first, which is available on all systems since
+ NT4 SP6 anyway. If that fails, call the simple version. */
+ version.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
+ if (!GetVersionEx (reinterpret_cast<LPOSVERSIONINFO>(&version)))
+ {
+ has_osversioninfoex = false;
+ version.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
+ GetVersionEx (reinterpret_cast<LPOSVERSIONINFO>(&version));
+ }
switch (version.dwPlatformId)
{
@@ -883,18 +889,14 @@ wincapc::init ()
break;
case 4:
os = "NT";
- if (strcmp (version.szCSDVersion, "Service Pack 4") < 0)
+ if (!has_osversioninfoex
+ && strcmp (version.szCSDVersion, "Service Pack 4") < 0)
caps = &wincap_nt4;
else
- {
- caps = &wincap_nt4sp4;
- if (strcmp (version.szCSDVersion, "Service Pack 6") >= 0)
- has_osversioninfoex = true;
- }
+ caps = &wincap_nt4sp4;
break;
case 5:
os = "NT";
- has_osversioninfoex = true;
switch (version.dwMinorVersion)
{
case 0:
@@ -903,8 +905,8 @@ wincapc::init ()
case 1:
caps = &wincap_xp;
- if (strcmp (version.szCSDVersion, "Service Pack 1") >= 0)
- ((wincaps *)this->caps)->has_gaa_prefixes = true;
+ if (version.wServicePackMajor < 1)
+ ((wincaps *)this->caps)->has_gaa_prefixes = false;
break;
default:
@@ -913,7 +915,6 @@ wincapc::init ()
break;
case 6:
os = "NT";
- has_osversioninfoex = true;
caps = &wincap_vista;
break;
default:
@@ -955,15 +956,8 @@ wincapc::init ()
break;
}
- if (has_osversioninfoex)
- {
- /* Request extended version to get server info.
- Available since NT4 SP6. */
- version.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
- GetVersionEx (reinterpret_cast<LPOSVERSIONINFO>(&version));
- if (version.wProductType != VER_NT_WORKSTATION)
- ((wincaps *)this->caps)->is_server = true;
- }
+ if (has_osversioninfoex && version.wProductType != VER_NT_WORKSTATION)
+ ((wincaps *)this->caps)->is_server = true;
BOOL is_wow64_proc = FALSE;
if (IsWow64Process (GetCurrentProcess (), &is_wow64_proc))