Hi, A user of Cygwin/Xfree86 reported that cygwin did not report an interface for his wireless network adapter. It seems that the GetIfTable function did not return all network adapters on his computer. As a workaround to this problem i changed the code to use GetIfEntry for each configured address.
I also had to change the algorithm for finding all addresses configured for one network adapter and changed the previous code which could only enumerate 10 addresses per adapter to use sprintf and raised that limit too. I also added code for getting the device metric for an interface. I'm not sure if this is correctly solved and I have no problems with removing this part again. 2002-11-09 Alexander Gottwald <[EMAIL PROTECTED]> * net.cc (get_2k_ifconf): Get the interface entries with the GetIfEntry call intead of the GetIfTable call. Query the interface metric from the IpForwardTable. Clean-up multiple IP address naming. bye ago -- [EMAIL PROTECTED] http://www.gotti.org ICQ: 126018723
--- winsup/cygwin/net.cc.orig Sat Nov 9 18:36:52 2002 +++ winsup/cygwin/net.cc Sat Nov 9 18:38:23 2002 @@ -1216,125 +1216,189 @@ static void get_2k_ifconf (struct ifconf *ifc, int what) { int cnt = 0; - char eth[2] = "/", ppp[2] = "/", slp[2] = "/", sub[2] = "0", tok[2] = "/"; + int ethId = 0, pppId = 0, slpId = 0, tokId = 0; /* Union maps buffer to correct struct */ struct ifreq *ifr = ifc->ifc_req; - DWORD if_cnt, ip_cnt, lip, lnp; - DWORD siz_if_table = 0; + DWORD ip_cnt, ipf_cnt, lip, lnp; DWORD siz_ip_table = 0; - PMIB_IFTABLE ift; + DWORD siz_ipfwd_table = 0; PMIB_IPADDRTABLE ipt; + PMIB_IFROW ifrow; + PMIB_IPFORWARDTABLE ipfwdt; 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)) + typedef struct ifcount_t { + DWORD ifIndex; + DWORD routeIndex; + DWORD metric; + size_t count; + unsigned int enumerated; // for eth0:1 + unsigned int classId; // for eth0, tok0 ... + + }; + ifcount_t *iflist, *ifEntry; + + if (GetIpAddrTable (NULL, &siz_ip_table, TRUE) == ERROR_INSUFFICIENT_BUFFER + && GetIpForwardTable(NULL, &siz_ipfwd_table, FALSE) == +ERROR_INSUFFICIENT_BUFFER + && (ifrow = (PMIB_IFROW) alloca (sizeof (MIB_IFROW))) + && (ipt = (PMIB_IPADDRTABLE) alloca (siz_ip_table)) + && (ipfwdt = (PMIB_IPFORWARDTABLE) alloca (siz_ipfwd_table)) + && !GetIpAddrTable (ipt, &siz_ip_table, TRUE) + && !GetIpForwardTable(ipfwdt, &siz_ipfwd_table, FALSE)) { - /* Iterate over all known interfaces */ - for (if_cnt = 0; if_cnt < ift->dwNumEntries; ++if_cnt) + iflist = (ifcount_t *)alloca(sizeof(ifcount_t) * (ipt->dwNumEntries + 1)); + memset(iflist, 0, sizeof(ifcount_t) * (ipt->dwNumEntries + 1)); + for (ip_cnt = 0; ip_cnt < ipt->dwNumEntries; ++ip_cnt) + { + ifEntry = iflist; + /* search for matching entry (and stop at first free entry) */ + while (ifEntry->count != 0) { + if (ifEntry->ifIndex == ipt->table[ip_cnt].dwIndex) + break; + ifEntry++; + } + if (ifEntry->count == 0) { + ifEntry->count = 1; + ifEntry->metric = 1; + ifEntry->ifIndex = ipt->table[ip_cnt].dwIndex; + } else { + ifEntry->count++; + } + } + // reset the last element. This is just the stopper for the loop. + iflist[ipt->dwNumEntries].count = 0; + + ifEntry = iflist; + while (ifEntry->count > 0) { + for (ipf_cnt = 0; ipf_cnt < ipfwdt->dwNumEntries; ++ipf_cnt) + if (ipfwdt->table[ipf_cnt].dwForwardIfIndex == ifEntry->ifIndex) { + ifEntry->routeIndex = ipf_cnt; + ifEntry->metric = ipfwdt->table[ipf_cnt].dwForwardMetric1; + break; + } + ifEntry++; + } + + /* Iterate over all configured IP-addresses */ + for (ip_cnt = 0; ip_cnt < ipt->dwNumEntries; ++ip_cnt) { - *sub = '0'; - /* Iterate over all configured IP-addresses */ - for (ip_cnt = 0; ip_cnt < ipt->dwNumEntries; ++ip_cnt) + memset (ifrow, 0, sizeof (MIB_IFROW)); + ifrow->dwIndex = ipt->table[ip_cnt].dwIndex; + if (GetIfEntry (ifrow) != NO_ERROR) + continue; + + ifcount_t *ifEntry = iflist; + /* search for matching entry (and stop at first free entry) */ + while (ifEntry->count != 0) { + if (ifEntry->ifIndex == ipt->table[ip_cnt].dwIndex) + break; + ifEntry++; + } + + /* Setup the interface name */ + switch (ifrow->dwType) { - /* Does the IP address belong to the interface? */ - if (ipt->table[ip_cnt].dwIndex == ift->table[if_cnt].dwIndex) - { - /* Setup the interface name */ - switch (ift->table[if_cnt].dwType) - { - case MIB_IF_TYPE_TOKENRING: - ++*tok; - strcpy (ifr->ifr_name, "tok"); - strcat (ifr->ifr_name, tok); - break; - case MIB_IF_TYPE_ETHERNET: - if (*sub == '0') - ++*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; - } - if (*sub > '0') - { - strcat (ifr->ifr_name, ":"); - strcat (ifr->ifr_name, sub); - } - ++*sub; - /* setup sockaddr struct */ - 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; + case MIB_IF_TYPE_TOKENRING: + if (ifEntry->enumerated == 0) { + ifEntry->classId = tokId++; + __small_sprintf(ifr->ifr_name, "tok%u", ifEntry->classId); + } else { + __small_sprintf(ifr->ifr_name, "tok%u:%u", ifEntry->classId, + ifEntry->enumerated-1); + } + ifEntry->enumerated++; + break; + case MIB_IF_TYPE_ETHERNET: + if (ifEntry->enumerated == 0) { + ifEntry->classId = ethId++; + __small_sprintf(ifr->ifr_name, "eth%u", ifEntry->classId); + } else { + __small_sprintf(ifr->ifr_name, "eth%u:%u", ifEntry->classId, + ifEntry->enumerated-1); + } + ifEntry->enumerated++; + break; + case MIB_IF_TYPE_PPP: + if (ifEntry->enumerated == 0) { + ifEntry->classId = pppId++; + __small_sprintf(ifr->ifr_name, "ppp%u", ifEntry->classId); + } else { + __small_sprintf(ifr->ifr_name, "ppp%u:%u", ifEntry->classId, + ifEntry->enumerated-1); + } + ifEntry->enumerated++; + break; + case MIB_IF_TYPE_SLIP: + if (ifEntry->enumerated == 0) { + ifEntry->classId = slpId++; + __small_sprintf(ifr->ifr_name, "slp%u", ifEntry->classId); + } else { + __small_sprintf(ifr->ifr_name, "slp%u:%u", ifEntry->classId, + ifEntry->enumerated-1); + } + ifEntry->enumerated++; + break; + case MIB_IF_TYPE_LOOPBACK: + strcpy (ifr->ifr_name, "lo"); + break; + default: + continue; + } + /* setup sockaddr struct */ + 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; + /* 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; + 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; + 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 >= ifrow->dwPhysAddrLen) + so->sa_data[i] = '\0'; + else + so->sa_data[i] = ifrow->bPhysAddr[i]; + so->sa_family = AF_INET; + break; + case SIOCGIFMETRIC: + ifr->ifr_metric = ifEntry->metric; + break; + case SIOCGIFMTU: + ifr->ifr_mtu = ifrow->dwMtu; + break; } + ++cnt; + if ((caddr_t)++ ifr > + ifc->ifc_buf + ifc->ifc_len - sizeof (struct ifreq)) + goto done; } } + done: /* Set the correct length */ ifc->ifc_len = cnt * sizeof (struct ifreq); --- winsup/cygwin/autoload.cc.orig Sat Nov 9 18:36:52 2002 +++ winsup/cygwin/autoload.cc Sat Nov 9 18:42:17 2002 @@ -485,7 +485,9 @@ LoadDLLfuncEx (WSAEventSelect, 12, ws2_3 LoadDLLfuncEx (WSAEnumNetworkEvents, 12, ws2_32, 1) LoadDLLfuncEx (GetIfTable, 12, iphlpapi, 1) +LoadDLLfuncEx (GetIfEntry, 4, iphlpapi, 1) LoadDLLfuncEx (GetIpAddrTable, 12, iphlpapi, 1) +LoadDLLfuncEx (GetIpForwardTable, 12, iphlpapi, 1) LoadDLLfunc (CoInitialize, 4, ole32) LoadDLLfunc (CoUninitialize, 0, ole32)