Getting the IP address and mask for ALL TCP/IP interfaces (Views: 28)
Problem/Question/Abstract: We have seen a lot of methods obtaining the IP address of a machine. This is the "correct" method listing all addresses, network masks, broadcast addresses and status for all interfaces, including the loopback 127.0.0.1 - Requires WinSock 2 Answer: This is a complete Delphi unit. By adding it to a project you can call : EnumInterfaces(var s string): Boolean; that returns a CRLF separated string of all IP addresses, netmasks, broadcast addresses and interface status. unit USock; interface uses Windows, Winsock; { This function enumerates all TCP/IP interfaces and returns a CRLF separated string containing: IP, NetMask, BroadCast-Address, Up/Down status, Broadcast support, Loopback If you feed this string to a wide TMEMO (to its memo.lines.text property) you will see cleary the results. To use this you need Win98/ME/2K, 95 OSR 2 or NT service pack #3 because WinSock 2 is used (WS2_32.DLL) } function EnumInterfaces(var sInt: string): Boolean; { Imported function WSAIOCtl from Winsock 2.0 - Winsock 2 is } { available only in Win98/ME/2K and 95 OSR2, NT srv pack #3 } function WSAIoctl(s: TSocket; cmd: DWORD; lpInBuffer: PCHAR; dwInBufferLen: DWORD; lpOutBuffer: PCHAR; dwOutBufferLen: DWORD; lpdwOutBytesReturned: LPDWORD; lpOverLapped: POINTER; lpOverLappedRoutine: POINTER): Integer; stdcall; external 'WS2_32.DLL'; { Constants taken from C header files } const SIO_GET_INTERFACE_LIST = $4004747F; IFF_UP = $00000001; IFF_BROADCAST = $00000002; IFF_LOOPBACK = $00000004; IFF_POINTTOPOINT = $00000008; IFF_MULTICAST = $00000010; type sockaddr_gen = packed record AddressIn: sockaddr_in; filler: packed array[0..7] of char; end; type INTERFACE_INFO = packed record iiFlags: u_long; // Interface flags iiAddress: sockaddr_gen; // Interface address iiBroadcastAddress: sockaddr_gen; // Broadcast address iiNetmask: sockaddr_gen; // Network mask end; implementation {------------------------------------------------------------------- 1. Open WINSOCK 2. Create a socket 3. Call WSAIOCtl to obtain network interfaces 4. For every interface, get IP, MASK, BROADCAST, status 5. Fill a CRLF separated string with this info 6. Finito --------------------------------------------------------------------} function EnumInterfaces(var sInt: string): Boolean; var s: TSocket; wsaD: WSADATA; NumInterfaces: Integer; BytesReturned, SetFlags: u_long; pAddrInet: SOCKADDR_IN; pAddrString: PCHAR; PtrA: pointer; Buffer: array[0..20] of INTERFACE_INFO; i: Integer; begin result := true; // Initialize sInt := ''; WSAStartup($0101, wsaD); // Start WinSock // You should normally check // for errors here :) s := Socket(AF_INET, SOCK_STREAM, 0); // Open a socket if (s = INVALID_SOCKET) then exit; try // Call WSAIoCtl PtrA := @bytesReturned; if (WSAIoCtl(s, SIO_GET_INTERFACE_LIST, nil, 0, @Buffer, 1024, PtrA, nil, nil) <> SOCKET_ERROR) then begin // If ok, find out how // many interfaces exist NumInterfaces := BytesReturned div SizeOf(INTERFACE_INFO); for i := 0 to NumInterfaces - 1 do // For every interface begin pAddrInet := Buffer[i].iiAddress.addressIn; // IP ADDRESS pAddrString := inet_ntoa(pAddrInet.sin_addr); sInt := sInt + ' IP=' + pAddrString + ','; pAddrInet := Buffer[i].iiNetMask.addressIn; // SUBNET MASK pAddrString := inet_ntoa(pAddrInet.sin_addr); sInt := sInt + ' Mask=' + pAddrString + ','; pAddrInet := Buffer[i].iiBroadCastAddress.addressIn; // Broadcast addr pAddrString := inet_ntoa(pAddrInet.sin_addr); sInt := sInt + ' Broadcast=' + pAddrString + ','; SetFlags := Buffer[i].iiFlags; if (SetFlags and IFF_UP) = IFF_UP then sInt := sInt + ' Interface UP,' // Interface up/down else sInt := sInt + ' Interface DOWN,'; if (SetFlags and IFF_BROADCAST) = IFF_BROADCAST then // Broadcasts sInt := sInt + ' Broadcasts supported,' // supported or else // not supported sInt := sInt + ' Broadcasts NOT supported,'; if (SetFlags and IFF_LOOPBACK) = IFF_LOOPBACK then // Loopback or sInt := sInt + ' Loopback interface' else sInt := sInt + ' Network interface'; // normal sInt := sInt + #13#10; // CRLF between // each interface end; end; except end; // // Close sockets // CloseSocket(s); WSACleanUp; result := false; end; end. here's a step-by-step on how to use it: 1. Copy/Paste the code to a text file and name it USock.pas (it's important that you name it like that, otherwise it won't work) 2. Open (Run) Delphi 3. Add a Memo control to the page and a button 4. Click on File/Save All and save the project somewhere (make a folder for it) 5. Put USock.pas in that folder 6. In Delphi, click on Project menu item and choose Add to Project 7. Select the USock.pas file and click on Open 8. NOW, doubleclick on the button you added to your project and write this: in VAR section, write: s: string After begin (the main part) write: EnumInterfaces(s); memo1.lines.text := s; So, the final procedure will look like: procedure TForm1.Button1Click(Sender: TObject); var s: string; begin EnumInterfaces(s); memo1.lines.text := s; end; 9. Now, go to the top of your unit to the USES section and add USock to other uses things there, it will look like: uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, USock; Then, run the project and click on that button. You will see the info in your memo box... Here's what i get (the second part of it): IP=127.0.0.1, Mask=255.0.0.0, Broadcast=255.255.255.255, Interface UP, Broadcasts supported, Loopback interface So, as you see, all that info is in "s" variable... |