HOWTO: Use Winsock to Enumerate Addresses

ID: Q129315


The information in this article applies to:


SUMMARY

Winsock offers several ways to obtain addressing information for TCP/IP-based machines. This article demonstrates how to obtain address information for IPX and NetBIOS under Windows NT.


MORE INFORMATION

Method One

AF_IPX

You can use this sample to give an IPX address:

Sample Code


   #include <winsock.h>
   #include <wsipx.h>
   #include <wsnwlink.h>

   #include <stdio.h>

   void main()
   {
      WSADATA        wsaData;
      int            cAdapters, res,
                     cbOpt  = sizeof( cAdapters ),
                     cbAddr = sizeof( SOCKADDR_IPX );

      SOCKET         s;
      SOCKADDR_IPX   Addr;

      if (WSAStartup(0x0101, &wsaData))
      {
         printf("WSAStartup failed %s\n", WSAGetLastError());
         return;
      }

      // Create IPX socket.
      s = socket( AF_IPX, SOCK_DGRAM, NSPROTO_IPX );

      if(s==INVALID_SOCKET)
         printf("Error: %u\n", WSAGetLastError());

      // Socket must be bound prior to calling IPX_MAX_ADAPTER_NUM.
      memset( &Addr, 0, sizeof( Addr ));
      Addr.sa_family = AF_IPX;
      res = bind( s, (SOCKADDR*) &Addr, cbAddr);
      if(res != 0)
         printf("Error: %u\n", WSAGetLastError());

      // Get the number of adapters => cAdapters.
      res = getsockopt( (SOCKET) s, NSPROTO_IPX, IPX_MAX_ADAPTER_NUM,
                  (char *) &cAdapters, &cbOpt );
      if(res != 0)
         printf("Error: %u\n", WSAGetLastError());
      // At this point cAdapters is the number of installed adapters.
      while ( cAdapters > 0 )
      {
         IPX_ADDRESS_DATA  IpxData;

         memset( &IpxData, 0, sizeof(IpxData));

         // Specify which adapter to check.
         IpxData.adapternum = cAdapters - 1;
         cbOpt = sizeof( IpxData );

         // Get information for the current adapter.
         res = getsockopt( s, NSPROTO_IPX, IPX_ADDRESS,
                     (char*) &IpxData, &cbOpt );
         if(res != 0)
            printf("Error: %u\n", WSAGetLastError());
         else
         {
            // IpxData contains the address for the current adapter.
            int i;
            printf("Net Number:   ");
            for (i=0;i<4;i++)
               printf("%02X",IpxData.netnum[i]);
            printf("\n");
            printf("Node Address: ");
            for (i=0;i<5;i++)
               printf("%02X-",IpxData.nodenum[i]);
            printf("%02X\n",IpxData.nodenum[i]);
         }

         cAdapters--;
      }

      WSACleanup();
      return;
   } 


AF_NETBIOS

The following sample uses the EnumProtocols() function to give lana numbers for the available NetBIOS transports. Additionally, under Winsock2, the function WSAEnumProtocols() replaces EnumProtocols(); it returns the same information as before, but also includes additional information. With both functions, the key is to take the absolute value of the iProtocol field of either the PROTOCOL_INFO or WSAPROTOCOL_INFO structure, which is the LANA number for that transport.

The PROTOCOL_INFO structure is returned by EnumProtocols(), while WSAEnumProtocols() uses the WSAPROTOCOL_INFO structure. This enumeration does not work under Windows NT 3.5 because of a bug in EnumProtocols(). Winsock 2 is available on Windows NT 4.0 or later.

NOTE: Winsock 2 is also available for Windows 95 and its functionality is built in to Windows 98.

Lastly, the iProtocol value for the transport corresponding to LANA 0 will be 0x80000000. The reason for this is protocol 0 is reserved for internal use.

Sample Code


   #include <windows.h>
   #include <assert.h>
   #include <nspapi.h>

   #include <stdio.h>
   void main()
   {
      DWORD          cb = 0;
      PROTOCOL_INFO *pPI;
      BOOL           pfLanas[100];

      int            iRes,
                     nLanas = sizeof(pfLanas) / sizeof(BOOL);

      // Specify NULL for lpiProtocols to enumerate all protocols.
      // First, determine the output buffer size.

      iRes = EnumProtocols( NULL, NULL, &cb );

      // Verify that the expected error was received.
      assert( iRes == -1 && GetLastError() == ERROR_INSUFFICIENT_BUFFER );
      if (!cb)
      {
         printf( "No available NetBIOS transports.\n");
         return;
      }

      // Allocate a buffer of the specified size.
      pPI = (PROTOCOL_INFO*) malloc( cb );

      // Enumerate all protocols.
      iRes = EnumProtocols( NULL, pPI, &cb );

      // EnumProtocols() lists each lana number twice, once for
      // SOCK_DGRAM and once for SOCK_SEQPACKET. Set a flag in pfLanas
      // so unique lanas can be identified.

      memset( pfLanas, 0, sizeof( pfLanas ));

      while (iRes > 0)
      {
         // Scan protocols looking for AF_NETBIOS.
         if ( pPI[--iRes].iAddressFamily == AF_NETBIOS )
            // Found one.
            pfLanas[ abs(pPI[iRes].iProtocol) ] = TRUE;
      }

      printf( "Available NetBIOS lana numbers: " );
      while( nLanas-- )
         if ( pfLanas[nLanas] )
            printf( "%d ", nLanas );

      printf( "\n" );
      free( pPI );
      return;
   } 


AF_APPLETALK

Address enumeration is not meaningful for AF_APPLETALK. On a multi-homed host with routing disabled, only the default adapter is used. If routing is enabled, a single AppleTalk address is used for all installed network adapters.

Method Two

Listed below is an example of how to use the WinSock database APIs to give IP addresses:

Sample Code


   #include <windows.h>
   #include <winsock.h>
   #include <stdio.h>

   void main()
   {
      WSADATA  wsaData;
      char     szHostname[100];
      HOSTENT *pHostEnt;
      int      nAdapter = 0;
      struct   sockaddr_in sAddr;

      if (WSAStartup(0x0101, &wsaData))
      {
         printf("WSAStartup failed %s\n", WSAGetLastError());
         return;
      }

      gethostname( szHostname, sizeof( szHostname ));
      pHostEnt = gethostbyname( szHostname );

      while ( pHostEnt->h_addr_list[nAdapter] )
      {
       // pHostEnt->h_addr_list[nAdapter] is the current address in host
       // order.

       // Copy the address information from the pHostEnt to a sockaddr_in
       // structure.
         memcpy ( &sAddr.sin_addr.s_addr, pHostEnt->h_addr_list[nAdapter],
                  pHostEnt->h_length);

         // Output the machines IP Address.
         printf("Name:    %s\nAddress: %s\n", pHostEnt->h_name,
                inet_ntoa(sAddr.sin_addr));

         nAdapter++;
      }
      WSACleanup();
      return;

   } 

Additional query words:


Keywords          : kbnetwork kbAPI kbNetBIOS kbNTOS350 kbNTOS351 kbSDKPlatform kbWinsock kbGrpNet 
Version           : 
Platform          : 
Issue type        : kbhowto 

Last Reviewed: March 20, 1999