Descrizione dell'interfaccia verso il device driver
La libreria PACKET95.DLL è la DLL di interfacciamento
tra il VXD catturatore di pacchetti VPACKET.VXD è le
applicazioni che per esso verranno scritte. Esponiamo qui di
seguito brevemente le API messe a disposizione dalla DLL.
Le strutture dati di PACKET95
La DLL utilizza due strutture dati fondamentali definite nel
file PACKET32.H. Esse sono :
A queste due si affianca una struttura definita in NTDDPACK.H
utilizzata per interrogare lNDIS mediante la funzione di PacketRequest.
Ne vedremo in seguito una descrizione.
STRUTTURA PACKET
La struttura PACKET è composta dai campi:
- hEvent
- Overlapped
- Buffer
- Length
- ulBytesReceived
- bIoComplete
Il campo hEvent è stato inserito per compatibilità
però non è utilizzato nelle API.
Il campo Overlapped è utilizzato per gestire le
operazioni di tipo asincrono; un esempio del suo utilizzo è
mostrato nella funzione PacketReceivePacket.
Questa struttura è già predefinita nell SDK di WINDOWS
95. In particolare la Overlapped ha un campo hEvent il quale
viene resettato con la opportuna funzione chiamata ResetEvent,
quando il pacchetto deve essere ricevuto in maniera asincrona.
La routine del VXD predisposta a ricevere i pacchetti dalla
scheda di rete imposta dunque tale evento allo scopo di segnalare
il completamento delloperazione.
Dal punto di vista della applicazione, non occorre andare a
vedere se levento è settato, poiché WINDOWS 95 mette a
disposizione la API GetOverLappedResult che va a controllare la
struttura automaticamente.
Il campo Buffer è un campo di tipo puntatore a void e
rappresenta il pacchetto vero e proprio, mentre il campo Length
dice quanti byte è lungo il buffer medesimo.
Il campo ulBytesReceived dice quanti byte del buffer
sono occupati dal pacchetto ricevuto ed infine il campo bIoComplete
indica se il pacchetto è stato riempito o no di dati validi da
una lettura asincrona. Viene inoltre resettato da una
PacketReceivePacket o una PacketSendPacket, mentre vengono
settati quando si fa una PacketWaitPacket.
STRUTTURA ADAPTER
è la struttura che descrive un adattatore ed è composta dei
campi:
Il campo hFile mantiene un puntatore allhandle
del VXD : infatti per comunicare direttamente con esso occorre
dunque effettuare delle DeviceIOControl utilizzando questo
handle. Comunque è fortemente sconsigliato colloquiare
direttamente con il VXD.
Infine il rimanente campo SymbolicLink il quale altro
non è che una stringa contenente il nome delladattatore
aperto.
STRUTTURA PACKET_OID_DATA
Tale struttura è composta dai campi seguenti:
Il campo Oid è un identificatore numerico che
specifica il tipo di query/set da effettuare sulladattatore
mediante la funzione PacketRequest. I possibili valori sono
definiti nel file di include NTDDNDIS.H : con tali valori
è possibile ad esempio richiedere lo stato dei contatori di
errore, lindirizzo MAC della scheda, la lista dei gruppi
multicast programmati sulla scheda e altre informazioni.
Il campo Length dice quale è la lunghezza del campo Data
e questultimo infine contiene le sequenze di byte formite a
seguito di query o da fornire per una operazione di set al NDIS.
La sua lunghezza è funzione del tipo di operazione da
realizzare.
Le routine di PACKET95
La DLL PACKET95 fornisce le funzioni necessarie per
spedire e ricevere un pacchetto, interrogare e impostare i
parametri di un adattatore di rete, aprire e chiudere un
adattatore ed infine gestire lallocazione dinamica delle
strutture di tipo PACKET.
Qui di seguito ne riportiamo la lista :
- PacketOpenAdapter: tale funzione prende in input il nome
delladattatore da aprire e restituisce il puntatore
ad una struttura ADAPTER opportunamente inizializzata. Il
nome deve essere uno di quelli riportati da
PacketGetAdapterNames.
- PacketCloseAdapter: tale funzione prende in ingresso un
puntatore ad una struttura di tipo ADAPTER e provvede a
deallocarla, chiudendo dunque ladattatore.
- PacketSendPacket: questa funzione accetta in ingresso un
puntatore ad una struttura ADAPTER, un puntatore ad una
struttura PACKET e un campo boolean. Il suo scopo è
quello di inviare il pacchetto contenuto nella struttura
PACKET verso ladattatore indicato da ADAPTER. Il
campo boolean indica se loperazione deve essere
completata in maniera sincrona o meno. Nel caso di
completamento asincrono occorre controllare il campo
bIOComplete della struttura PACKET per verificare
lavvenuto trasferimento, oppure invocare la
PacketWaitPacket per attendere sino ad operazione
avvenuta.
In uscita la funzione restituisce TRUE se è stato
completato il trasferimento oppure FALSE nel caso
contrario.
La modalità sincrona consiste nellavviare
unoperazione ed attendere il completamento della
medesima.
La modalità asincrona consiste invece
nellavviare unoperazione e di ritornare
subito senza attenderne il suo completamento.
Successivamente occorrerà controllare se
loperazione è stata portata a termine con successo
o è ancora pendente.
Pare chiaro che questa modalità è particolarmente
adatta per realizzare il cuore del catturatore di
pacchetti; infatti basta predisporre un buffer circolare
e su ogni elemento di questo andare a effettuare delle
letture asincrone. Sarà poi il VXD che si preoccuperà
di riempire i vari elementi del buffer con i pacchetti
corrispondenti alle richieste non appena la loro
ricezione è stata completata.
- PacketReceivePacket: questa funzione ha lo stesso
prototipo della PacketSendPacket e per essa quale tutto
quanto detto sopra.
- PacketRequest: Accetta in ingresso il puntatore ad una
struttura ADAPTER, uno ad una struttura PACKET_OID_DATA e
un campo SET di tipo boolean.
Lobiettivo è quello di fare una query (SET = 0) o
un set (SET = 1) verso ladattatore specificato da
ADAPTER. Chiaramente, la struttura PACKET_OID_DATA verrà
riempita o conterrà i dati da trasferire verso il VXD a
seconda delloperazione impostata. La funzione
ritorna TRUE se loperazione è andata a buon fine
FALSE altrimenti.
La PacketRequest è in grado di effettuare numerosi tipi
di query/set impostabili mediante le costanti definite
nel file NTDDNDIS.H.
Nota: occorre controllare sempre il
valore ritornato dalla PacketRequest in quanto
non tutte le query definite dallNDIS sono
poi implementate nel driver di rete della scheda
su cui si fa la query! Segue un esempio di
query fatta con lNDIS che è poi quella che
si trova nel codice sorgente allegato:
// Setto il campo Oid al valore
OID_802_3_PERMANENT_ADDRESS
OidData->Oid=OID_802_3_PERMANENT_ADDRESS;
OidData->Length=6;
// Vedi il file ntddndis.h
Status=PacketRequest(AdapterObject,FALSE,OidData);
Qui la query richiede lindirizzo
permanente della scheda di rete ed è definita
dalla costante OID_802_3_PERMANENT_ADDRESS.
In funzione del loro tipo le query/set usano
dati di dimensione variabile: per sapere quanti
byte riservare per la struttura occore consultare
lhelp del DDK per NT 4.0 (in quello per
WINDOWS 95 non è citato).
|
- PacketAllocatePacket: ha la funzione di restituire una
struttura PACKET allocata in maniera corretta.
Nota: pur essendo la struttura
allocata in maniera corretta, il campo Buffer non
viene impostato; occorre infatti allocare
esternamente un buffer e legarlo alla struttura
PACKET con la PacketInitPacket. |
- PacketInitPacket: è la funzione utilizzata in
congiunzione alla PacketAllocatePacket per impostare una
struttura PACKET. Accetta in ingresso il puntatore alla
PACKET da impostare, il puntatore al buffer che conterrà
il pacchetto e la dimensione del buffer.
- PacketFreePacket: libera la struttura PACKET passata come
parametro.
Nota: occorre liberare
preventivamente il buffer. |
- PacketWaitPacket: accetta come parametri il puntatore ad
una struttura ADAPTER e ad una struttura PACKET. La sua
funzione è quella di attendere se il pacchetto
identificato dalla PACKET non è stato riempito con i
dati. Ritorna TRUE se non ci sono stati problemi nel
completare loperazione, altrimenti ritorna FALSE.
Per capire poi quale errore si è verificato, basta
richiamare la GetLastError.
- PacketSetFilter: serve ad impostare un filtro hardware
sui pacchetti catturati: le costanti che definiscono tali
filtri sono definiti in NTDDNDIS.H . La routine
accetta come parametri il puntatore alla struttura
ADAPTER che indica ladattatore su cui operare ed un
intero che identifica il tipo di filtro. Il valore
ritornato è TRUE se loperazione è stata compiuta
con successo, FALSE altrimenti.
I filtri hardware impostabili sono diversi, eccone la
descrizione dei più utili:
- Modalità PROMISCUA: si imposta mediante
la costante NDIS_PACKET_TYPE_PROMISCUOUS e
consiste nella cattura di tutti i pacchetti anche
quelli non destinati alla scheda.
- Modalità DIRETTA: si imposta mediante la
costante NDIS_PACKET_TYPE_DIRECTED e consiste
nella cattura di tutti i pacchetti aventi come
destinazione la scheda su cui si sta impostando
la modalità.
- Modalità BROADCAST: si imposta mediante
la costante NDIS_PACKET_TYPE_BROADCAST e consiste
nella cattura dei pacchetti broadcast.
- Modalità MULTICAST: si imposta mediante
la costante NDIS_PACKET_TYPE_MULTICAST e consiste
nella cattura del traffico dei gruppi multicast
cui la scheda di rete è iscritta.
- PacketGetAdapterNames: tale funzione va invocata prima
dellapertura di un qualsiasi adattatore. Infatti
essa restituisce una stringa con i nomi degli adattatori
installati nel sistema semplicemente separati da uno
spazio. La stringa è NULL terminated ed i parametri che
essa accetta sono: un buffer in cui verrà restituita la
stringa e un puntatore ad intero. Il puntatore ad intero
punta in ingresso alla lunghezza del buffer passato alla
funzione ed in uscita punta alla lunghezza della stringa
restituita.
- PacketResetAdapter: tale funzione resetta
ladattatore passato come argomento. Restituisce
TRUE se loperazione è andata a buon fine
altrimenti ritorna FALSE.