Home | Chi sono | Contattami
 

Progr. lineare

Delphi
 
Componenti
  Database
 
Miei articoli

Windows

Miei articoli 

 

Enumerare le interfacce di rete con relative caratteristiche (ipconfig /all)


In questo articolo viene descritto come riprodurre il comportamento dell'eseguibile di sistema ipconfig il cui obiettivo quello di enumerare le interfacce di rete e restituirne una descrizione. Bene, passiamo subito ai fatti.

1. Enumerazione interfacce di rete

Spulciando nel Platform SDK si pu vedere che le funzioni necessarie a raggiungere l'obiettivo prefissato sono implementate nella dll iphlapi.dll. Il fulcro di tutto l'api win32 GetAdaptersInfo (anche se per windows xp e windows 2003 consigliato l'utilizzo dell'api win32 GetAdaptersAddresses).

1.1 GetAdaptersInfo

La funzione GetAdaptersinfo consente l'enumerazione delle interfacce di rete. Di seguito la definizione:

function GetAdaptersInfo(pAdapterInfo: PIP_ADAPTER_INFO; var pOutBufLen: cardinal ): cardinal; stdcall;

E' necessario ora definire il tipo PIP_ADAPTER_INFO ed i tipi in esso contenuti:

const MAX_ADAPTER_DESCRIPTION_LENGTH = 128; MAX_ADAPTER_NAME_LENGTH = 256; MAX_ADAPTER_ADDRESS_LENGTH = 8; DEFAULT_MINIMUM_ENTITIES = 32; MAX_HOSTNAME_LEN = 128; MAX_DOMAIN_NAME_LEN = 128; MAX_SCOPE_ID_LEN = 256; // // IP_ADDRESS_STRING - store an IP address as a dotted decimal string // type PIP_MASK_STRING = ^IP_MASK_STRING; IP_ADDRESS_STRING = record S: array [0..15] of Char; end; PIP_ADDRESS_STRING = ^IP_ADDRESS_STRING; IP_MASK_STRING = IP_ADDRESS_STRING; // // IP_ADDR_STRING - store an IP address with its corresponding subnet mask, // both as dotted decimal strings // PIP_ADDR_STRING = ^IP_ADDR_STRING; IP_ADDR_STRING = record Next: PIP_ADDR_STRING; IpAddress: IP_ADDRESS_STRING; IpMask: IP_MASK_STRING; Context: Cardinal; end; // // ADAPTER_INFO - per-adapter information. All IP addresses are stored as // strings // PIP_ADAPTER_INFO = ^IP_ADAPTER_INFO; IP_ADAPTER_INFO = record Next: PIP_ADAPTER_INFO; ComboIndex: Cardinal; AdapterName: array [0..MAX_ADAPTER_NAME_LENGTH + 3] of Char; Description: array [0..MAX_ADAPTER_DESCRIPTION_LENGTH + 3] of Char; AddressLength: Cardinal; Address: array [0..MAX_ADAPTER_ADDRESS_LENGTH - 1] of BYTE; Index: Cardinal; Type_: Cardinal; DhcpEnabled: Cardinal; CurrentIpAddress: PIP_ADDR_STRING; IpAddressList: IP_ADDR_STRING; GatewayList: IP_ADDR_STRING; DhcpServer: IP_ADDR_STRING; HaveWins: Boolean; PrimaryWinsServer: IP_ADDR_STRING; SecondaryWinsServer: IP_ADDR_STRING; LeaseObtained: Integer; LeaseExpires: Integer; end;

Analizziamo ora input ed output della GetAdaptersInfo:

Input

  • pAdapterInfo: parametro di tipo PIP_ADAPTER_INFO; si tratta di una lista linkata che contiene tutte le interfacce di rete: i primi 4 bytes del record IP_ADAPTER_INFO (campo Next) puntano infatti all'elemento successivo.
  • pOutBufLen: dimensione totale dei dati puntati da pAdapterInfo (tutti gli elementi della lista linkata). Se il valore che viene settato inferiore al valore effettivo allora la funzione restituisce l'errore ERROR_BUFFER_OVERFLOW (valore decimale 111) e la variabile pOutBufLen riceve la dimensione esatta.

Output

  • ERROR_BUFFER_OVERFLOW: valore decimale 111: la dimensione del buffer specificata da pOutBufLen troppo piccola; pOutBufLen riceve la dimensione esatta
  • ERROR_INVALID_PARAMETER: valore decimale 87:  pAdapterInfo non settato (nil) oppure impossibile accedere in lettura/scrittura a uno dei 2 parametri o ad entrambi
  • ERROR_NO_DATA: valore decimale 232: nessuna informazione disponibile
  • ERROR_NOT_SUPPORTED: valore decimale 55: l'api GetAdaptersInfo non supportata nel sistema operativo
  • In tutti gli altri casi (output diverso da 0 e diverso dai valori appena elencati): usare GetLastError

In caso di successo la funzione restituisce 0.

Molte delle informazioni che ci interessano relativamente ad una interfaccia di rete sono contenute in IP_ADAPTER_INFO; tuttavia possiamo approfondire ulteriormente il risultato ottenuto tramite l'api win32 GetPerAdapterInfo che andiamo ad analizzare.

1.2 GetPerAdapterInfo

L'api win32 GetPerAdapterInfo restituisce ulteriori informazioni su una interfaccia di rete specifica; l'unico motivo per cui abbiamo tirato in ballo questa funzione che ci consente di determinare l'elenco dei server dns.

function GetPerAdapterInfo(IfIndex: Cardinal; pPerAdapterInfo: PIP_PER_ADAPTER_INFO; var pOutBufLen: Cardinal ): Cardinal; stdcall; external 'iphlpapi.dll' name 'GetPerAdapterInfo';

Definiamo ora il tipo PIP_PER_ADAPTER_INFO

PIP_PER_ADAPTER_INFO = ^IP_PER_ADAPTER_INFO; IP_PER_ADAPTER_INFO = record AutoconfigEnabled: Cardinal; AutoconfigActive: Cardinal; CurrentDnsServer: PIP_ADDR_STRING; DnsServerList: IP_ADDR_STRING; end;

Il campo che ci interessa DnsServerList, una lista linkata contenente l'elenco dei dns server.

Diamo ora una breve occhiata ai parametri della funzione:

  • IfIndex: indice dell'interfaccia
  • pPerAdapterInfo: puntatore all'informazione sull'interfaccia
  • pOutBufLen: dimensione del buffer in output: stesse considerazioni relative all'api GetAdaptersInfo vista in precedenza

In caso di successo l'output 0; i possibili errori sono analoghi a quelli descritti per la GetAdaptersInfo

2. Esempio

Eccoci arrivati ad un semplice esempio di utilizzo delle api appena analizzate: ci serve solo una form con un bottone ed un campo TMemo per il risultato

procedure TForm1.Button1Click(Sender: TObject); var Adapters, Adapter: PIP_ADAPTER_INFO; Size, Size2: ULONG; IpAddrString: PIP_ADDR_STRING; GatewayString: PIP_ADDR_STRING; DnsServerString: PIP_ADDR_STRING; pPerAdapterInfo: PIP_PER_ADAPTER_INFO; i: integer; begin Size := 0; if GetAdaptersInfo(nil, Size) <> ERROR_BUFFER_OVERFLOW then Exit; Adapters := AllocMem(Size); try if GetAdaptersInfo(Adapters, Size) = 0 then //elenco delle interfacce di rete begin Adapter := Adapters; while Adapter <> nil do (*loop sulle interfacce di rete*) begin Memo1.Lines.Add(pChar(@Adapter^.AdapterName) + '---' + pChar(@Adapter^.Description)); Memo1.Lines.Add(' ' + 'Elenco Indirizzi IP:'); //elenco degli indirizzi IP di una interfaccia di rete IpAddrString := @Adapter^.IpAddressList; (*loop sugli indirizzi IP di una interfaccia di rete*) while IpAddrString <> nil do begin Memo1.Lines.Add(' ' + ' ' + (IpAddrString^.IpAddress.S) + '---' + (IpAddrString^.IpMask.S)); IpAddrString := IpAddrString^.Next; end; (*loop sugli indirizzi IP di una interfaccia di rete*) Memo1.Lines.Add(' ' + 'Elenco Gateways:'); //elenco degli indirizzi IP di una interfaccia di rete GatewayString := @Adapter^.GatewayList; (*loop sugli indirizzi IP di una interfaccia di rete*) while GatewayString <> nil do begin Memo1.Lines.Add(' ' + ' ' + (GatewayString^.IpAddress.S)); GatewayString := GatewayString^.Next; end; (*loop sugli indirizzi IP di una interfaccia di rete*) Size2 := 0; if GetPerAdapterInfo(Adapter^.Index, nil, Size2) <> ERROR_BUFFER_OVERFLOW then Exit; pPerAdapterInfo := AllocMem(Size2); GetPerAdapterInfo(Adapter^.Index, pPerAdapterInfo, Size2); Memo1.Lines.Add(' ' + 'Elenco Server DNS:'); DnsServerString := @pPerAdapterInfo^.DnsServerList; (*loop sugli indirizzi IP di una interfaccia di rete*) while DnsServerString <> nil do begin Memo1.Lines.Add(' ' + ' ' + (DnsServerString^.IpAddress.S)); DnsServerString := DnsServerString^.Next; end; (*loop sugli indirizzi IP di una interfaccia di rete*) Adapter := Adapter^.Next; end; (*loop sulle interfacce di rete*) end; finally FreeMem(Adapters); FreeMem(pPerAdapterInfo); end; end;

NetInterfaces

 

 
 
Your Ad Here