[omniORB] Warning: WSAIoctl SIO_ADDRESS_LIST_QUERY failed

Harri Pasanen harri.pasanen@trema.com
Fri, 05 Apr 2002 16:19:29 +0200


Mac wrote:

> 
> yep i came across this too..here's a fix...the function below uses
> SIO_GET_INTERFACE_LIST instead of SIO_ADDRESS_LIST_QUERY in the ioctl
> call. I've only tested this on NT sp6a (not w2000). & i don't think it'll
> work for pre sp4 versions of NT due to a tweak they made with the
> INTERFACE_INFO struct to accomdate IPv6.
> 
> so inside tcpTransportImpl.cc replace the win32_get_ifinfo func with the
> one below.
> 
> static
> void win32_get_ifinfo(omnivector<const char*>& ifaddrs) {
> 
>   SocketHandle_t sock;
> 
>   sock = socket(INETSOCKET,SOCK_STREAM,0);
> 
>   DWORD lastlen = 0;
>   DWORD len = 10 * sizeof(INTERFACE_INFO);
>   DWORD retlen=0;
>   
>   INTERFACE_INFO *addressBuffer=NULL;
> 
>   while ( 1 )
>   {
>     // There is no way to know for sure the buffer is big enough to get
>     // the info for all the interfaces. We work around this by calling
>     // the ioctl 2 times and increases the buffer size in the 2nd call.
>     addressBuffer = (INTERFACE_INFO*) malloc(len);
> 
> 
>     if ( WSAIoctl(sock,SIO_GET_INTERFACE_LIST, NULL,0,
>     (LPVOID)addressBuffer,(DWORD)len,(LPDWORD)&retlen,
>                   NULL,NULL) == SOCKET_ERROR )
>  {
>  
>   int err = WSAGetLastError();
> 
>   free(addressBuffer);
> 
>   if ( err != WSAENOBUFS || lastlen != 0 )
>   {
>    if ( omniORB::trace(2) )
>    {
>      omniORB::logger log;
>      log << "Warning: WSAIoctl SIO_ADDRESS_LIST_QUERY failed. Unable to
>      obtain the list of all interface addresses.\n";
>    }
>    return;
>   }
>   len *= 2;
>     }
>     else
>  {
>   if ( retlen <= len )
>    break; // Success, len is large enough
>  
>   len = retlen;
>     }
>     
>   }
>   CLOSESOCKET(sock);
> 
>   int numAddresses = retlen / sizeof(INTERFACE_INFO);
>   for (int i = 0; i < numAddresses; i++)
>   {
>  // Only add the address if the interface is running
>  if (addressBuffer[i].iiFlags & IFF_UP)
>  {
>   if (addressBuffer[i].iiAddress.Address.sa_family == INETSOCKET )
>   {
>     struct sockaddr_in* iaddr = &addressBuffer[i].iiAddress.AddressIn;
>     CORBA::String_var s;
>     s = tcpConnection::ip4ToString(iaddr->sin_addr.s_addr);
>     ifaddrs.push_back(s._retn());
>   }
>  }
>   }
>   free(addressBuffer);
> 
> 
>   if ( orbParameters::dumpConfiguration || omniORB::trace(20) ) {
>     omniORB::logger log;
>     omnivector<const char*>::iterator i = ifaddrs.begin();
>     omnivector<const char*>::iterator last = ifaddrs.end();
>     log << "My addresses are: \n";
>     while ( i != last ) {
>       log << "omniORB: " << (const char*)(*i) << "\n";
>       i++;
>     }
>   }
> }
> 
> 
> oh and you may need to #include <ws2tcpip.h>


Thanks for the cue.   It seems to work both for NT and Win2000.

I reworked it a bit though, as the while loop and the exit conditions were 
not too clear in the original code.  The original code actual called 
WSAIoctl twice even when the first time was successful.

Here is my last version, where we just punt if the machine has more than 64 
interfaces.  How likely is that anyway?    Now it is done as in ACE.


static
void win32_get_ifinfo(omnivector<const char*>& ifaddrs) {

  SocketHandle_t sock;

  sock = socket(INETSOCKET,SOCK_STREAM,0);

  INTERFACE_INFO info[64];  // Assume max 64 interfaces
  DWORD retlen;
  
  if ( WSAIoctl(sock, SIO_GET_INTERFACE_LIST, NULL,0,
                (LPVOID)&info, sizeof(info), (LPDWORD)&retlen,
                  NULL,NULL) == SOCKET_ERROR ) {
      if ( omniORB::trace(1) ) {
        omniORB::logger log;
        int err = WSAGetLastError();
        log << "Warning: WSAIoctl SIO_GET_INTERFACE_LIST failed.\n"
            << "Unable to obtain the list of all interface addresses. 
WSAGetLastError() = " << err << endl;
      }
      return;
  }
  CLOSESOCKET(sock);

  int numAddresses = retlen / sizeof(INTERFACE_INFO);
  for (int i = 0; i < numAddresses; i++) 
    {
      // Only add the address if the interface is running
      if (info[i].iiFlags & IFF_UP)
        {
          if (info[i].iiAddress.Address.sa_family == INETSOCKET ) 
            {
              struct sockaddr_in* iaddr = &info[i].iiAddress.AddressIn;
              CORBA::String_var s;
              s = tcpConnection::ip4ToString(iaddr->sin_addr.s_addr);
              ifaddrs.push_back(s._retn());
            }
        }
    }

  if ( orbParameters::dumpConfiguration || omniORB::trace(20) ) {
    omniORB::logger log;
    omnivector<const char*>::iterator i = ifaddrs.begin();
    omnivector<const char*>::iterator last = ifaddrs.end();
    log << "My addresses are: \n";
    while ( i != last ) {
      log << "omniORB: " << (const char*)(*i) << "\n";
      i++;
    }
  }
}