Newsgroup: it.comp.lang.visual-basic
Titolo: [?] Ping con il vb...domanda

Salve,
mi stavo chiedendo se è possibile tramite vb pingare
qualcuno...precisaente è possibile mandare dei pacchetti ip ad un un altro
pc?
Che potrei usare, il componente winsock vuole la specifica di una
porta host e di una locale, quindi dire che non va bene...ci sono altri
componenti per caso? Insomma...se qualcuno ne sa qualcosa che mi illumini
please :)
Saluti...
--------------------------------
Inviato via 
http://usenet.iol.it

 Se preferisci un mini-tutorial, è pronto anche quello.
Visto che sono arrivate ad oggi N° 63 richieste per questa "cosa",
vorrei chiedere di evitare di inviarne altre. Grazie.
Vedrò di passare la simulazione al SC al più presto.
Nel frattempo posto qui il mini-tutorial, nel caso servisse ad altri.
----------------------------------------------------------------------
Il termine "Ping" deriva dal termine gergale usato in marina
per riferirsi agli echo di risposta di un segnale sonar.
I "Pings" sono appunto i segnali auditivi prodotti dal dispositivo
sonar quando identifica un rimbalzo del segnale su un oggetto
solido.
Similmente, in informatica un Ping è un "segnale" che viene
inviato ad un host per verificare il suo stato attivo.
Se l'host è attivo, fa "rimbalzare" la richiesta, ritornando
al mittente il suo stato e altre informazioni.
Nella definizione dei Sockets Berkeley standard, Ping è un echo
di request/reply che si ottiene tramite un socket di tipo
SOCK_RAW e un protocollo IPPROTO_ICMP o IPPROTO_RAW.
I raw socket vengono in genere creati per bypassare i layer nello
stack TCP/IP e generare pacchetti che il sistema (il Kernel in Unix,
Winsock in Windows) non supporta in maniera esplicita.
La funzione socket() di Winsock2 permette la creazione di tali
socket:
es.
 hSock = socket(AF_INET, SOCK_RAW, <protocol>)
Specificando IPPROTO_RAW, l'applicazione dovrà farsi carico
di creare l'header di definizione del protocollo. Può essere
utile in sistemi "chiusi" o che utilizzano pacchetti proprietari.
Il numero di protocollo viene inserito nella struttura
dell'header IP. IPPROTO_RAW inserisce 0.
La maggior parte dei sistemi operativi ha una socket option
IP_HDRINCL (raw IP) che permette di definire l'header del protocollo.
Per quanto riguarda i sistemi Windows, il supporto è abbastanza
limitato:
                             Win95           Win9x       WinNT    Windows
                         Winsock 1.1   Winsock 2      4.0           2000
Raw ICMP             No                  Si              Si               Si
IP_HDRINCL        No                  No            No             Si
Raw TCP/UDP       No                  No            No             No
Da tenere presente che con WinNT 4.0 e Win2000, solo gli utenti che
sono membri del gruppo Administrators possono aprire dei raw socket.
Un Ping si attua inviando un echo packet ICMP (internet control
message protocol - altro protocollo IP distinto da TCP o UDP).
Il sistema dispone degli strumenti per inviare pacchetti echo - per
adeguarsi alle specifiche TCP/IP - ma non ha mezzi per generare
questi pacchetti, per il fatto che non è richiesto.
La generazione di "ping packet" è invece delegata a software che
agisce a livello application. La generazione del pacchetto avviene
quindi nello "user space". Per questo un'applicazione, per generare
dei "ping packet", deve interagire con il sistema a basso livello
e avere quindi un livello di accesso che permetta questa interazione.
In Windows NT, il privilegio di accesso "Act as part of the
Operating System" è in genere concesso solo agli utenti del
gruppo Administrators.
Come evidenziato nella tabella precedente, i raw socket ICMP
sono supportati dalla versione 2 di Winsock. Quindi le versioni
di Win95 senza upgrade (la versione fornita con il SO è la 1.1)
non dispongono di questa funzionalità.
Occorre anche dire che la versione 2 del socket dispone di una
implementazione dei raw socket che può essere definita
approssimativa. In particolare, nessuno degli stack Microsoft
riporta errori Winsock se viene ricevuto un messaggio di errore
ICMP. Ad esempio, se un sistema riceve un datagram e la porta
di destinazione del datagram non è collegata, il sistema risponde
con un "ICMP Destination Unreachable" (porta non raggiungibile).
L'applicazione chiamante dovrebbe ricevere un errore
10061 (WSAECONNREFUSED), ma così non è. L'errore viene perso.
Un "workaround" potrebbe essere quello di utilizzare la funzione
bind(), specificando come indirizzo INADDR_ANY. Purtroppo molti
datagrammi vengono ugualmente persi, senza contare che
l'applicazione non è in grado di ricevere gli echo request
inviati dalla macchina su cui gira.
Inoltre, utilizzando IPPROTO_RAW, viene inviato un header mal
formato (il valore del protocollo è 255 invece di 0) e l'header
stesso è inviato come "dati". Il ricevente risponde con un errore
ICMP "protocol unreachable".
Questi problemi non si riscontrano con Windows 2000.
Per motivi legati a queste carenze implementative, particolarmente
in relazione alla versione 1.1 del socket, Microsoft mette a
disposizione una libreria (icmp.dll) che consente l'invio e la
ricezione di echo ICMP nonché la manipolazione delle impostazioni
degli header IP. La libreria si appoggia solamente a Kernel32, non
a Winsock32.
In particolare, la libreria esporta le funzioni:
IcmpCreateFile()
IcmpCloseHandle()
IcmpSendEcho()
La funzione IcmpSendEcho() viene utilizzata per inviare un
echo (ping) ad un host, dato il suo indirizzo IP.
In Visual Basic, le funzioni vengono dichiarate in questo modo:
Declare Function IcmpCreateFile Lib "icmp.dll" () As Long
Declare Function IcmpCloseHandle Lib "icmp.dll" _
   (ByVal IcmpHandle As Long) As Long
Declare Function IcmpSendEcho Lib "icmp.dll" _
   (ByVal IcmpHandle As Long, _
    ByVal DestinationAddress As Long, _
    ByVal RequestData As String, _
    ByVal RequestSize As Integer, _
    ByVal RequestOptions As Long, _
    ReplyBuffer As ICMP_ECHO_REPLY, _
    ByVal ReplySize As Long, _
    ByVal TimeOut As Long) As Long
La funzione IcmpCreateFile() viene utilizzata, similmente
alla funzione del Kernel CreateFile(), per inizializzare
un handle che istanzia un Raw Socket ICMP.
La funzione IcmpSendEcho() si occupa di inviare la richiesta
di echo all'host specificato.
I parametri della funzione:
IcmpHandle: l'handle restituito da IcmpCreateFile()
DestinationAddress: indirizzo, in Network Byte Order, dell'host
di destinazione dell'echo. L'indirizzo è in formato Long.
Con "Network Byte Order" si intende la rappresentazione
esadecimale degli ottetti che compongono l'indirizzo IP.
La funzione, come evidente, tratta solamente indirizzi IpV4,
composto da 4 ottetti, quindi 32 bit. Un indirizzo IpV6, ai
fini di routing, è composto da 128 bit.
Winsock mette a disposizione la funzione inet_addr() per la
conversione di un indirizzo IP nel formato stringa nella
sua rappresentazione numerica in network byte order.
RequestData: stringa di caratteri, per un massimo di 32,
che rappresenta il messaggio inviato all'host. Il set di
caratteri utilizzato è l'Ascii standard a 7 bit (tutti i
caratteri con codice inferiore a 128). L'eventuale conversione
della stringa dal formato ANSI multi-bye in Ascii è viene
effettuata dalla funzione.
RequestSize: dimensione, in byte, della stringa definita da
RequestData.
RequestOptions: puntatore alla struttura ip_option_information.
In genere si imposta a 0 (null), dato che la struttura viene
inizializzata tramite il parametro ReplyBuffer.
Type IP_OPTIONS_INFORMATION
   TTL             As Byte
   Tos             As Byte
   Flags           As Byte
   OptionsSize     As Byte
   OptionsData     As Long
End Type
TTL:    Time to Live -> tempo di vita del pacchetto
Flags:  Generalmente = 0
Per ulteriori informazioni fare riferimento all'RFC 791.
ReplyBuffer: puntatore alla struttura icmp_echo_reply.
Nella struttura vengono restituite alcune informazioni
e i dati del datagramma.
 Public Type ICMP_ECHO_REPLY
    address         As Long
    Status          As Long
    RoundTripTime   As Long
    DataSize        As Integer
    Reserved        As Integer
    DataPointer     As Long
    Options         As IP_OPTIONS_INFORMATION
    data            As String * 250
 End Type
 address: indirizzo in network byte order dell'host che
 ha effettivamente risposto alla richiesta di echo.
 L'indirizzo può essere diverso da quello dell'host
 chiamato.
 Status: 0 se la richiesta ha avuto successo, altrimenti
 è il codice dell'errore. I codici di errore sono riportati
 nella simulazione Ping.
 RoundTripTime: tempo approssimato (in ms) impiegato dal
 pacchetto per giungere a destinazione.
 Datasize: dimensione del pacchetto dati ricevuto. Deve
 essere uguale alle dimensioni del pacchetto inviato (32 byte).
 Reserved: riservato. Sempre 0.
 Datapointer: puntatore alla sezione data in coda alla
 struttura.
 Options: puntatore alla struttura IP_OPTIONS_INFORMATION
TimeOut: tempo di attesa (in ms) prima di considerare perso il
pacchetto inviato. Il tempo di timeout è stabilito dall'applicazione.
Occorre valutare con attenzione l'impostazione di questo periodo
di attesa. Un timeout troppo basso porta a considerare "unreachable"
(quindi potenzialmente off-line o inesistente) un host che impiega
molto tempo a rispondere.
Il workflow di una richiesta echo ICMP è il seguente:
Inizializzazione del socket
    --> Funzione WSAStartUp()
Creazione di una porta ICMP
    --> Funzione IcmpCreateFile()
Invio di un echo all'indirizzo IP
    --> Funzione IcmpSendEcho()
Chiusura della handle
    --> Funzione IcmpCloseHandle()
Reset del socket
    --> Funzione WSACleanUp()
-----------------------------------------------------------------
Come evidenziato, la funzione IcmpSendEcho() accetta solo
indirizzi in Network Byte Order (Long). Ossia non è possibile
specificare un FQDN (Fully Qualified Domain Name) come indirizzo.
Per richiedere un echo ad un host di cui si conosce solo l'FQDN
(es. 
www.microsoft.com
), occorre ottenere il suo indirizzo IP dal
DNS di riferimento (il DNS dell'Internet Service Provider).
A questo scopo si usa la funzione Winsock gethostbyname() a cui
si passa il nome dell'host in formato stringa.
La simulazione dispone un wrapper a questa funzione per mezzo
della funzione GetHostIPAddress().
Public Function GetHostIPAddress( _
 lpszHostName As String, _
 strHostAlias As String) As String
lpszHostName [IN]:  nome dell'host di cui si chiede l'indirizzo IP
strHostAlias [OUT]: in uscita rende l'FQDN dell'host cercato
La funzione restituisce l'indirizzo IP dell'host in formato stringa.
Per contro, quando si richiede un echo ad un host di cui si conosce
l'indirizzo IP, normalmente non viene restituito il suo FQDN.
La simulazione, a scopo di esempio, implementa anche questa
funzionalità.
La funzione Winsock utilizzata è gethostbyaddr(), il cui wrapper
è costituito dalla funzione GetHostNameByIPAddress()
Public Function GetHostNameByIPAddress( _
 lpszAddress As String) As String
lpszAddress: indirizzo IP dell'host
La funzione restituisce l'FQDN dell'host
-----------------------------------------------------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%