From 9182099c105321c24a12b53183f92cc58f4e0580 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Wed, 7 Feb 2001 22:50:50 +0000 Subject: [PATCH] * autoload.cc: Add LoadDLLinitfunc for iphlpapi.dll. Add LoadDLLfuncEx statements for GetIfTable@12 and GetIpAddrTable@12. * fhandler_socket.cc (fhandler_socket::ioctl): Move variable definitions to the beginning of the function to allow better debugging. Add handling for SIOCGIFHWADDR, SIOCGIFMETRIC and SIOCGIFMTU. * net.cc: Include iphlpapi.h. (get_2k_ifconf): Rewritten. Uses IP Helper API now. (get_nt_ifconf): Add handling for SIOCGIFHWADDR, SIOCGIFMETRIC and SIOCGIFMTU. (get_95_ifconf): Ditto. Renamed from `get_9x_ifconf'. (get_ifconf): Name loopback `lo' instead of `lo0' as in Linux. Add handling for SIOCGIFHWADDR, SIOCGIFMETRIC and SIOCGIFMTU. Call `get_95_ifconf' only on Windows 95, `get_nt_ifconf' only on Windows NT < Service Pack 3, `get_2k_ifconf otherwise. * include/asm/socket.h: Add defines for SIOCGIFHWADDR, SIOCGIFMETRIC and SIOCGIFMTU. * include/cygwin/if.h: Add `ifr_hwaddr', `ifr_metric' and `ifr_mtu'. (struct ifreq): Add `ifru_hwaddr'. --- winsup/cygwin/ChangeLog | 21 ++ winsup/cygwin/autoload.cc | 26 +++ winsup/cygwin/fhandler_socket.cc | 31 ++- winsup/cygwin/include/asm/socket.h | 9 +- winsup/cygwin/include/cygwin/if.h | 6 + winsup/cygwin/net.cc | 333 ++++++++++++++++------------- 6 files changed, 263 insertions(+), 163 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index aa137bcd9..24d127736 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,24 @@ +Wed Feb 7 22:22:00 2001 Corinna Vinschen + + * autoload.cc: Add LoadDLLinitfunc for iphlpapi.dll. + Add LoadDLLfuncEx statements for GetIfTable@12 and GetIpAddrTable@12. + * fhandler_socket.cc (fhandler_socket::ioctl): Move variable + definitions to the beginning of the function to allow better debugging. + Add handling for SIOCGIFHWADDR, SIOCGIFMETRIC and SIOCGIFMTU. + * net.cc: Include iphlpapi.h. + (get_2k_ifconf): Rewritten. Uses IP Helper API now. + (get_nt_ifconf): Add handling for SIOCGIFHWADDR, SIOCGIFMETRIC + and SIOCGIFMTU. + (get_95_ifconf): Ditto. Renamed from `get_9x_ifconf'. + (get_ifconf): Name loopback `lo' instead of `lo0' as in Linux. + Add handling for SIOCGIFHWADDR, SIOCGIFMETRIC and SIOCGIFMTU. + Call `get_95_ifconf' only on Windows 95, `get_nt_ifconf' only + on Windows NT < Service Pack 3, `get_2k_ifconf otherwise. + * include/asm/socket.h: Add defines for SIOCGIFHWADDR, SIOCGIFMETRIC + and SIOCGIFMTU. + * include/cygwin/if.h: Add `ifr_hwaddr', `ifr_metric' and `ifr_mtu'. + (struct ifreq): Add `ifru_hwaddr'. + Tue Feb 6 15:04:00 2001 Corinna Vinschen * syscalls.cc (stat_worker): Add a check for the special case when diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index f7b0a62ef..00ee37b2c 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -175,6 +175,28 @@ LoadDLLinitfunc (ws2_32) return 0; } +LoadDLLinitfunc (iphlpapi) +{ + HANDLE h; + static NO_COPY LONG here = -1L; + + while (InterlockedIncrement (&here)) + { + InterlockedDecrement (&here); + Sleep (0); + } + + if (iphlpapi_handle) + /* nothing to do */; + else if ((h = LoadLibrary ("iphlpapi.dll")) != NULL) + iphlpapi_handle = h; + else if (!iphlpapi_handle) + api_fatal ("could not load iphlpapi.dll, %E"); + + InterlockedDecrement (&here); + return 0; +} + static void __stdcall dummy_autoload (void) __attribute__ ((unused)); static void __stdcall dummy_autoload (void) @@ -313,5 +335,9 @@ LoadDLLfunc (socket, 12, wsock32) LoadDLLinit (ws2_32) LoadDLLfuncEx (WSADuplicateSocketA, 12, ws2_32, 1) LoadDLLfuncEx (WSASocketA, 24, ws2_32, 1) + +LoadDLLinit (iphlpapi) +LoadDLLfuncEx (GetIfTable, 12, iphlpapi, 1) +LoadDLLfuncEx (GetIpAddrTable, 12, iphlpapi, 1) } } diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index 17a6ff42b..e80a7f24b 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -159,20 +159,20 @@ fhandler_socket::ioctl (unsigned int cmd, void *p) { extern int get_ifconf (struct ifconf *ifc, int what); /* net.cc */ int res; - struct ifconf *ifc; - struct ifreq *ifr; + struct ifconf ifc, *ifcp; + struct ifreq *ifr, *ifrp; sigframe thisframe (mainthread); switch (cmd) { case SIOCGIFCONF: - ifc = (struct ifconf *) p; - if (ifc == 0) + ifcp = (struct ifconf *) p; + if (!ifcp) { set_errno (EINVAL); return -1; } - res = get_ifconf (ifc, cmd); + res = get_ifconf (ifcp, cmd); if (res) debug_printf ("error in get_ifconf\n"); break; @@ -194,14 +194,14 @@ fhandler_socket::ioctl (unsigned int cmd, void *p) case SIOCGIFBRDADDR: case SIOCGIFNETMASK: case SIOCGIFADDR: + case SIOCGIFHWADDR: + case SIOCGIFMETRIC: + case SIOCGIFMTU: { - char buf[2048]; - struct ifconf ifc; - ifc.ifc_len = sizeof (buf); - ifc.ifc_buf = buf; - struct ifreq *ifrp; + ifc.ifc_len = 2048; + ifc.ifc_buf = (char *) alloca (2048); - struct ifreq *ifr = (struct ifreq *) p; + ifr = (struct ifreq *) p; if (ifr == 0) { debug_printf ("ifr == NULL\n"); @@ -235,6 +235,15 @@ fhandler_socket::ioctl (unsigned int cmd, void *p) 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; + break; + case SIOCGIFMTU: + ifr->ifr_mtu = ifrp->ifr_mtu; + break; } break; } diff --git a/winsup/cygwin/include/asm/socket.h b/winsup/cygwin/include/asm/socket.h index 905e81505..aa1aa7535 100644 --- a/winsup/cygwin/include/asm/socket.h +++ b/winsup/cygwin/include/asm/socket.h @@ -23,11 +23,14 @@ #define SIOCGLOWAT _IOR('s', 3, u_long) /* get low watermark */ /* Needed for if queries */ -#define SIOCGIFCONF _IOW('s', 100, struct ifconf) /* get if list */ -#define SIOCGIFFLAGS _IOW('s', 101, struct ifreq) /* Get if flags */ -#define SIOCGIFADDR _IOW('s', 102, struct ifreq) /* Get if addr */ +#define SIOCGIFCONF _IOW('s', 100, struct ifconf) /* get if list */ +#define SIOCGIFFLAGS _IOW('s', 101, struct ifreq) /* Get if flags */ +#define SIOCGIFADDR _IOW('s', 102, struct ifreq) /* Get if addr */ #define SIOCGIFBRDADDR _IOW('s', 103, struct ifreq) /* Get if broadcastaddr */ #define SIOCGIFNETMASK _IOW('s', 104, struct ifreq) /* Get if netmask */ +#define SIOCGIFHWADDR _IOW('s', 105, struct ifreq) /* Get hw addr */ +#define SIOCGIFMETRIC _IOW('s', 106, struct ifreq) /* get metric */ +#define SIOCGIFMTU _IOW('s', 107, struct ifreq) /* get MTU size */ #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 fe0b8b4c1..977166ed7 100644 --- a/winsup/cygwin/include/cygwin/if.h +++ b/winsup/cygwin/include/cygwin/if.h @@ -27,6 +27,7 @@ extern "C" { struct ifreq { #define IFNAMSIZ 16 +#define IFHWADDRLEN 6 union { char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ @@ -36,6 +37,7 @@ struct ifreq 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; @@ -47,6 +49,10 @@ struct ifreq #define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ #define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ #define ifr_flags ifr_ifru.ifru_flags /* flags */ +#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ +#define ifr_metric ifr_ifru.ifru_metric /* metric */ +#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ + /* * Structure used in SIOCGIFCONF request. diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index 5603a215e..fcada7b7f 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -17,6 +17,7 @@ details. */ #include #include #include +#include #include #include @@ -1048,159 +1049,120 @@ getdomainname (char *domain, int len) /* Fill out an ifconf struct. */ /* - * IFCONF Windows 2000: - * Look at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\ - Parameters\Interfaces - * Each subkey is an interface. + * IFCONF 98/ME, NTSP4, W2K: + * Use IP Helper Library */ static void get_2k_ifconf (struct ifconf *ifc, int what) { - HKEY key; - int cnt = 1; + int cnt = 0; + char eth[2] = "/", ppp[2] = "/", slp[2] = "/"; /* Union maps buffer to correct struct */ struct ifreq *ifr = ifc->ifc_req; - if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, - "SYSTEM\\" - "CurrentControlSet\\" - "Services\\" - "Tcpip\\" - "Parameters\\" - "Interfaces", - 0, KEY_READ, &key) == ERROR_SUCCESS) + DWORD if_cnt, ip_cnt, lip, lnp; + DWORD siz_if_table = 0; + DWORD siz_ip_table = 0; + PMIB_IFTABLE ift; + PMIB_IPADDRTABLE ipt; + struct sockaddr_in *sa = NULL; + struct sockaddr *so = NULL; + + if (GetIfTable(NULL, &siz_if_table, TRUE) == ERROR_INSUFFICIENT_BUFFER && + GetIpAddrTable(NULL, &siz_ip_table, TRUE) == ERROR_INSUFFICIENT_BUFFER && + (ift = (PMIB_IFTABLE) alloca (siz_if_table)) && + (ipt = (PMIB_IPADDRTABLE) alloca (siz_ip_table)) && + !GetIfTable(ift, &siz_if_table, TRUE) && + !GetIpAddrTable(ipt, &siz_ip_table, TRUE)) { - HKEY ikey; - unsigned long lip, lnp; - struct sockaddr_in *sa = NULL; - char name[256]; - DWORD size; - char eth[2] = "/", ppp[2] = "/"; - - for (int idx = 0; - RegEnumKeyEx (key, idx, name, (size = 256, &size), - NULL, NULL, 0, NULL) == ERROR_SUCCESS; - ++idx) + for (if_cnt = 0; if_cnt < ift->dwNumEntries; ++if_cnt) { - if (RegOpenKeyEx (key, name, 0, KEY_READ, &ikey) != ERROR_SUCCESS) - continue; - - /* If the "NTEContextList" value not exists, the subkey - is irrelevant. */ - if (RegQueryValueEx (ikey, "NTEContextList", - NULL, NULL, NULL, &size) != ERROR_SUCCESS) - { - RegCloseKey (ikey); - continue; - } - - if ((caddr_t) ++ifr > ifc->ifc_buf - + ifc->ifc_len - - sizeof (struct ifreq)) - { - RegCloseKey (ikey); - break; - } - - char ipaddress[256], netmask[256]; - char dhcpaddress[256], dhcpnetmask[256]; - - if (RegQueryValueEx (ikey, "IPAddress", - NULL, NULL, - (unsigned char *) ipaddress, - (size = 256, &size)) == ERROR_SUCCESS - && RegQueryValueEx (ikey, "SubnetMask", - NULL, NULL, - (unsigned char *) netmask, - (size = 256, &size)) == ERROR_SUCCESS) - { - /* ppp interfaces don't have the "AddressType" value. */ - if (RegQueryValueEx (ikey, "AddressType", - NULL, NULL, NULL, &size) == ERROR_SUCCESS) - { - ++*eth; - strcpy (ifr->ifr_name, "eth"); - strcat (ifr->ifr_name, eth); - } - else - { - ++*ppp; - strcpy (ifr->ifr_name, "ppp"); - strcat (ifr->ifr_name, ppp); - } - - memset (&ifr->ifr_addr, '\0', sizeof ifr->ifr_addr); - if (cygwin_inet_addr (ipaddress) == 0L - && RegQueryValueEx (ikey, "DhcpIPAddress", - NULL, NULL, - (unsigned char *) dhcpaddress, - (size = 256, &size)) - == ERROR_SUCCESS - && RegQueryValueEx (ikey, "DhcpSubnetMask", - NULL, NULL, - (unsigned char *) dhcpnetmask, - (size = 256, &size)) - == ERROR_SUCCESS) - { - switch (what) - { - case SIOCGIFCONF: - case SIOCGIFADDR: - sa = (struct sockaddr_in *) &ifr->ifr_addr; - sa->sin_addr.s_addr = cygwin_inet_addr (dhcpaddress); - break; - case SIOCGIFBRDADDR: - lip = cygwin_inet_addr (dhcpaddress); - lnp = cygwin_inet_addr (dhcpnetmask); - sa = (struct sockaddr_in *) &ifr->ifr_broadaddr; - sa->sin_addr.s_addr = lip & lnp | ~lnp; - break; - case SIOCGIFNETMASK: - sa = (struct sockaddr_in *) &ifr->ifr_netmask; - sa->sin_addr.s_addr = - cygwin_inet_addr (dhcpnetmask); - break; - } - } - else - { - switch (what) - { - case SIOCGIFCONF: - case SIOCGIFADDR: - sa = (struct sockaddr_in *) &ifr->ifr_addr; - sa->sin_addr.s_addr = cygwin_inet_addr (ipaddress); - break; - case SIOCGIFBRDADDR: - lip = cygwin_inet_addr (ipaddress); - lnp = cygwin_inet_addr (netmask); - sa = (struct sockaddr_in *) &ifr->ifr_broadaddr; - sa->sin_addr.s_addr = lip & lnp | ~lnp; - break; - case SIOCGIFNETMASK: - sa = (struct sockaddr_in *) &ifr->ifr_netmask; - sa->sin_addr.s_addr = cygwin_inet_addr (netmask); - break; - } - } - sa->sin_family = AF_INET; - sa->sin_port = 0; - ++cnt; - } - - RegCloseKey (ikey); - } - - RegCloseKey (key); + switch (ift->table[if_cnt].dwType) + { + case MIB_IF_TYPE_ETHERNET: + ++*eth; + strcpy (ifr->ifr_name, "eth"); + strcat (ifr->ifr_name, eth); + break; + case MIB_IF_TYPE_PPP: + ++*ppp; + strcpy (ifr->ifr_name, "ppp"); + strcat (ifr->ifr_name, ppp); + break; + case MIB_IF_TYPE_SLIP: + ++*slp; + strcpy (ifr->ifr_name, "slp"); + strcat (ifr->ifr_name, slp); + break; + case MIB_IF_TYPE_LOOPBACK: + strcpy (ifr->ifr_name, "lo"); + break; + default: + continue; + } + for (ip_cnt = 0; ip_cnt < ipt->dwNumEntries; ++ip_cnt) + if (ipt->table[ip_cnt].dwIndex == ift->table[if_cnt].dwIndex) + { + switch (what) + { + case SIOCGIFCONF: + case SIOCGIFADDR: + sa = (struct sockaddr_in *) &ifr->ifr_addr; + sa->sin_addr.s_addr = ipt->table[ip_cnt].dwAddr; + sa->sin_family = AF_INET; + sa->sin_port = 0; + break; + case SIOCGIFBRDADDR: + sa = (struct sockaddr_in *) &ifr->ifr_broadaddr; +#if 0 + /* Unfortunately, the field returns only crap. */ + sa->sin_addr.s_addr = ipt->table[ip_cnt].dwBCastAddr; +#else + lip = ipt->table[ip_cnt].dwAddr; + lnp = ipt->table[ip_cnt].dwMask; + sa->sin_addr.s_addr = lip & lnp | ~lnp; + sa->sin_family = AF_INET; + sa->sin_port = 0; +#endif + break; + case SIOCGIFNETMASK: + sa = (struct sockaddr_in *) &ifr->ifr_netmask; + sa->sin_addr.s_addr = ipt->table[ip_cnt].dwMask; + sa->sin_family = AF_INET; + sa->sin_port = 0; + break; + case SIOCGIFHWADDR: + so = &ifr->ifr_hwaddr; + for (UINT i = 0; i < IFHWADDRLEN; ++i) + if (i >= ift->table[if_cnt].dwPhysAddrLen) + so->sa_data[i] = '\0'; + else + so->sa_data[i] = ift->table[if_cnt].bPhysAddr[i]; + so->sa_family = AF_INET; + break; + case SIOCGIFMETRIC: + ifr->ifr_metric = 1; + break; + case SIOCGIFMTU: + ifr->ifr_mtu = ift->table[if_cnt].dwMtu; + break; + } + ++cnt; + if ((caddr_t) ++ifr > + ifc->ifc_buf + ifc->ifc_len - sizeof (struct ifreq)) + goto done; + break; + } + } } - +done: /* Set the correct length */ ifc->ifc_len = cnt * sizeof (struct ifreq); } /* - * IFCONF Windows NT: + * IFCONF Windows NT < SP4: * Look at the Bind value in * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Linkage\ * This is a REG_MULTI_SZ with strings of the form: @@ -1217,6 +1179,7 @@ get_nt_ifconf (struct ifconf *ifc, int what) HKEY key; unsigned long lip, lnp; struct sockaddr_in *sa = NULL; + struct sockaddr *so = NULL; DWORD size; int cnt = 1; char *binding = (char *) 0; @@ -1315,18 +1278,35 @@ get_nt_ifconf (struct ifconf *ifc, int what) case SIOCGIFADDR: sa = (struct sockaddr_in *) &ifr->ifr_addr; sa->sin_addr.s_addr = cygwin_inet_addr (dhcpaddress); + sa->sin_family = AF_INET; + sa->sin_port = 0; break; case SIOCGIFBRDADDR: lip = cygwin_inet_addr (dhcpaddress); lnp = cygwin_inet_addr (dhcpnetmask); sa = (struct sockaddr_in *) &ifr->ifr_broadaddr; sa->sin_addr.s_addr = lip & lnp | ~lnp; + sa->sin_family = AF_INET; + sa->sin_port = 0; break; case SIOCGIFNETMASK: sa = (struct sockaddr_in *) &ifr->ifr_netmask; sa->sin_addr.s_addr = cygwin_inet_addr (dhcpnetmask); + sa->sin_family = AF_INET; + sa->sin_port = 0; break; + case SIOCGIFHWADDR: + so = &ifr->ifr_hwaddr; + memset (so->sa_data, 0, IFHWADDRLEN); + so->sa_family = AF_INET; + break; + case SIOCGIFMETRIC: + ifr->ifr_metric = 1; + break; + case SIOCGIFMTU: + ifr->ifr_mtu = 1500; + break; } } else @@ -1337,21 +1317,36 @@ get_nt_ifconf (struct ifconf *ifc, int what) case SIOCGIFADDR: sa = (struct sockaddr_in *) &ifr->ifr_addr; sa->sin_addr.s_addr = cygwin_inet_addr (ip); + sa->sin_family = AF_INET; + sa->sin_port = 0; break; case SIOCGIFBRDADDR: lip = cygwin_inet_addr (ip); lnp = cygwin_inet_addr (np); sa = (struct sockaddr_in *) &ifr->ifr_broadaddr; sa->sin_addr.s_addr = lip & lnp | ~lnp; + sa->sin_family = AF_INET; + sa->sin_port = 0; break; case SIOCGIFNETMASK: sa = (struct sockaddr_in *) &ifr->ifr_netmask; sa->sin_addr.s_addr = cygwin_inet_addr (np); + sa->sin_family = AF_INET; + sa->sin_port = 0; break; + case SIOCGIFHWADDR: + so = &ifr->ifr_hwaddr; + memset (so->sa_data, 0, IFHWADDRLEN); + so->sa_family = AF_INET; + break; + case SIOCGIFMETRIC: + ifr->ifr_metric = 1; + break; + case SIOCGIFMTU: + ifr->ifr_mtu = 1500; + break; } } - sa->sin_family = AF_INET; - sa->sin_port = 0; ++cnt; } } @@ -1364,7 +1359,7 @@ get_nt_ifconf (struct ifconf *ifc, int what) } /* - * IFCONF Windows 9x: + * IFCONF Windows 95: * HKLM/Enum/Network/MSTCP/"*" * -> Value "Driver" enthält Subkey relativ zu * HKLM/System/CurrentControlSet/Class/ @@ -1381,11 +1376,12 @@ get_nt_ifconf (struct ifconf *ifc, int what) * */ static void -get_9x_ifconf (struct ifconf *ifc, int what) +get_95_ifconf (struct ifconf *ifc, int what) { HKEY key; unsigned long lip, lnp; struct sockaddr_in *sa = NULL; + struct sockaddr *so = NULL; FILETIME update; LONG res; DWORD size; @@ -1455,20 +1451,35 @@ get_9x_ifconf (struct ifconf *ifc, int what) case SIOCGIFADDR: sa = (struct sockaddr_in *) &ifr->ifr_addr; sa->sin_addr.s_addr = cygwin_inet_addr (ip); + sa->sin_family = AF_INET; + sa->sin_port = 0; break; case SIOCGIFBRDADDR: lip = cygwin_inet_addr (ip); lnp = cygwin_inet_addr (np); sa = (struct sockaddr_in *) &ifr->ifr_broadaddr; sa->sin_addr.s_addr = lip & lnp | ~lnp; + sa->sin_family = AF_INET; + sa->sin_port = 0; break; case SIOCGIFNETMASK: sa = (struct sockaddr_in *) &ifr->ifr_netmask; sa->sin_addr.s_addr = cygwin_inet_addr (np); + sa->sin_family = AF_INET; + sa->sin_port = 0; break; + case SIOCGIFHWADDR: + so = &ifr->ifr_hwaddr; + memset (so->sa_data, 0, IFHWADDRLEN); + so->sa_family = AF_INET; + break; + case SIOCGIFMETRIC: + ifr->ifr_metric = 1; + break; + case SIOCGIFMTU: + ifr->ifr_mtu = 1500; + break; } - sa->sin_family = AF_INET; - sa->sin_port = 0; } RegCloseKey (subkey); @@ -1554,7 +1565,7 @@ get_ifconf (struct ifconf *ifc, int what) } /* Set up interface lo0 first */ - strcpy (ifr->ifr_name, "lo0"); + strcpy (ifr->ifr_name, "lo"); memset (&ifr->ifr_addr, '\0', sizeof (ifr->ifr_addr)); switch (what) { @@ -1562,32 +1573,56 @@ get_ifconf (struct ifconf *ifc, int what) case SIOCGIFADDR: sa = (struct sockaddr_in *) &ifr->ifr_addr; sa->sin_addr.s_addr = htonl (INADDR_LOOPBACK); + sa->sin_family = AF_INET; + sa->sin_port = 0; break; case SIOCGIFBRDADDR: lip = htonl (INADDR_LOOPBACK); lnp = cygwin_inet_addr ("255.0.0.0"); sa = (struct sockaddr_in *) &ifr->ifr_broadaddr; sa->sin_addr.s_addr = lip & lnp | ~lnp; + sa->sin_family = AF_INET; + sa->sin_port = 0; break; case SIOCGIFNETMASK: sa = (struct sockaddr_in *) &ifr->ifr_netmask; sa->sin_addr.s_addr = cygwin_inet_addr ("255.0.0.0"); + sa->sin_family = AF_INET; + sa->sin_port = 0; + break; + case SIOCGIFHWADDR: + ifr->ifr_hwaddr.sa_family = AF_INET; + memset (ifr->ifr_hwaddr.sa_data, 0, IFHWADDRLEN); + break; + case SIOCGIFMETRIC: + ifr->ifr_metric = 1; + break; + case SIOCGIFMTU: + /* This funny value is returned by `ifconfig lo' on Linux 2.2 kernel. */ + ifr->ifr_mtu = 3924; break; default: set_errno (EINVAL); return -1; } - sa->sin_family = AF_INET; - sa->sin_port = 0; OSVERSIONINFO os_version_info; memset (&os_version_info, 0, sizeof os_version_info); os_version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); GetVersionEx (&os_version_info); - if (os_version_info.dwPlatformId != VER_PLATFORM_WIN32_NT) - get_9x_ifconf (ifc, what); - else if (os_version_info.dwMajorVersion <= 4) + /* We have a win95 version... */ + if (os_version_info.dwPlatformId != VER_PLATFORM_WIN32_NT + && (os_version_info.dwMajorVersion < 4 + || (os_version_info.dwMajorVersion == 4 + && os_version_info.dwMinorVersion == 0))) + get_95_ifconf (ifc, what); + /* ...and a NT <= SP3 version... */ + else if (os_version_info.dwPlatformId == VER_PLATFORM_WIN32_NT + && (os_version_info.dwMajorVersion < 4 + || (os_version_info.dwMajorVersion == 4 + && strcmp (os_version_info.szCSDVersion, "Service Pack 4") < 0))) get_nt_ifconf (ifc, what); + /* ...and finally a "modern" version for win98/ME, NT >= SP4 and W2K! */ else get_2k_ifconf (ifc, what);