E' capitato che qualche studente mi chiedesse come mai gli indirizzi IPv4 hanno "quello strano formato di quattro cifre separate da punti". Ebbene la risposta e' molto semplice, e puo' essere facilmente indagata con un po' di codice.
La notazione dotted-quad presenta quattro gruppi di cifre comprese fra 0 e 255. E' facile notare che per rappresentare 256 valori (da 0 a 255) occorre esattamente un byte, e che quattro byte corrispondono a 32 bit, valore ben "noto" in informatica. E in effetti la correlazione non e' casuale: la notazione dotted-quad nasconde ciascuno dei quattro byte che corrispondono ad un numero identificativo, l'indirizzo ip appunto.
E' possibile verificare quanto detto mediante un piccolo programma C che riporto di seguito nella versione per Linux (su BSD le librerie cambiano leggermente):
#include
#include
#include
#include
#include
#include
#include
int main( int argc, char** argv ){
if( argc < 2 ){
perror( "\nOccorre specificare nome host e numero di porta\n");
exit( EXIT_FAILURE );
}
// estraggo parametri da linea di comando
char *hostName = argv[1];
char *port = argv[2];
// creazione nuova struttura addressinfo
struct addrinfo *aInfo = malloc( sizeof( struct addrinfo ) * 1);
// mi serve un puntatore (non inizializzato) per la struttura risultante
// dal lookup di un host
struct addrinfo *lookupResults;
// compilo i campi della struttura
memset( aInfo, 0, sizeof( struct addrinfo ) ); // azzeramento struttura in memoria
aInfo->ai_family = AF_INET; // utilizzo IP
aInfo->ai_socktype = SOCK_STREAM; // utilizza TCP
aInfo->ai_protocol = 0; // protocollo specificato (tutti)
aInfo->ai_canonname = NULL; // nome simbolico host
aInfo->ai_addr = NULL;
aInfo->ai_next = NULL;
printf("\nCreata struttura addressinfo per nome simbolico host %s e servizio %s\n",
hostName, port );
// eseguo lookup host
int lookupResultCode = getaddrinfo( hostName, // nodo
argv[2], // servizio
aInfo, // informazioni per lookup
&lookupResults
);
// se ho codice diverso da zero allora sono in errore
if( lookupResultCode != 0 ){
printf( "\nRisultato lookup [%d] = %s\n", lookupResultCode,
gai_strerror(lookupResultCode) );
exit( EXIT_FAILURE );
}
// se sono qui ho effettuato il lookup, devo iterare su tutti i possibili
// risultati
struct addrinfo *currentResult;
for( currentResult = lookupResults; currentResult != NULL; currentResult = currentResult->ai_next ){
printf( "\n*** Risultato di lookup ***\n" );
printf( "\n\tNome canonico:\t%s", currentResult->ai_canonname );
printf( "\n\tLunghezza indirizzo:\t%d", currentResult->ai_addrlen );
// conversione a struttura socket address per internet
struct sockaddr_in *socketAddress = currentResult->ai_addr;
// stampa dei campi
printf( "\n\tPorta:\t%d", socketAddress->sin_port );
struct in_addr addressIP = socketAddress->sin_addr;
char* buffer = malloc( 24 * sizeof(char) );
inet_ntop( AF_INET, &addressIP, buffer, currentResult->ai_addrlen );
printf( "\n\tIndirizzo grezzo:\t%d", addressIP.s_addr );
printf( "\n\tIndirizzo tradotto:\t%s", buffer );
int i = 0;
int mask = 0xFF;
for( i = 0; i < 4; i++ ){
printf( "\n\tPezzo di indirizzo %d:\t%d",
i, ( (addressIP.s_addr) >> (8*i) ) & mask);
}
printf( "\n-----\n" );
}
}
Il programma, seppur abbastanza lungo per essere un esempio didattico, e' molto semplice: si vuole ricerca l'indirizzo IPv4 mediante lookup (del resolver) di un sito internet e del relativo servizio, per poi estrarre i singoli pezzi dell'indirizzo e suddividerli in byte. Per meglio comprendere si consideri la seguente invocazione:
$ ./net.exe www.kde.org 80
Creata struttura addressinfo per nome simbolico host www.kde.org e servizio 80
*** Risultato di lookup ***
Nome canonico: (null)
Lunghezza indirizzo: 16
Porta: 20480
Indirizzo grezzo: -94370770
Indirizzo tradotto: 46.4.96.250
Pezzo di indirizzo 0: 46
Pezzo di indirizzo 1: 4
Pezzo di indirizzo 2: 96
Pezzo di indirizzo 3: 250
-----
La parte interessante e' l'indirizzo grezzo: il valore riportato rappresenta 32 bit di informazione che identificano l'host www.kde.org. Tale indirizzo non e' facilmente memorizzabile da un umano e comunque ha una forma "strana" (e' perfino negativo!). L'indirizzo tradotto, quello in notazione dotted-quad, viene ottenuto mediante la funzione inet_ntop(..) che converte il numero unico di 32 bit in una stringa dotted-quad. Sarebbe possibile estrarre i singoli pezzi da 1 byte con una serie di "and" logici, come fa in effetti il programma a livello didattico. Tuttavia tale metodo non e' consigliato poiche' non tiene conto dell'ordinamento dei byte che dipende dalla architettura di sistema (little-endian, big-endian).
Ad ogni modo, a livello didattico, il programma preleva ogni singolo byte dell'indirizzo IPv4 e lo mette in "and" logico con 0xFF (255) al fine di estrarre ogni singolo valore della notazione dotted-quad.
Ed ecco svelato il mistero dietro alla notazione dotted-quad.
La notazione dotted-quad presenta quattro gruppi di cifre comprese fra 0 e 255. E' facile notare che per rappresentare 256 valori (da 0 a 255) occorre esattamente un byte, e che quattro byte corrispondono a 32 bit, valore ben "noto" in informatica. E in effetti la correlazione non e' casuale: la notazione dotted-quad nasconde ciascuno dei quattro byte che corrispondono ad un numero identificativo, l'indirizzo ip appunto.
E' possibile verificare quanto detto mediante un piccolo programma C che riporto di seguito nella versione per Linux (su BSD le librerie cambiano leggermente):
#include
#include
#include
#include
#include
#include
#include
int main( int argc, char** argv ){
if( argc < 2 ){
perror( "\nOccorre specificare nome host e numero di porta\n");
exit( EXIT_FAILURE );
}
// estraggo parametri da linea di comando
char *hostName = argv[1];
char *port = argv[2];
// creazione nuova struttura addressinfo
struct addrinfo *aInfo = malloc( sizeof( struct addrinfo ) * 1);
// mi serve un puntatore (non inizializzato) per la struttura risultante
// dal lookup di un host
struct addrinfo *lookupResults;
// compilo i campi della struttura
memset( aInfo, 0, sizeof( struct addrinfo ) ); // azzeramento struttura in memoria
aInfo->ai_family = AF_INET; // utilizzo IP
aInfo->ai_socktype = SOCK_STREAM; // utilizza TCP
aInfo->ai_protocol = 0; // protocollo specificato (tutti)
aInfo->ai_canonname = NULL; // nome simbolico host
aInfo->ai_addr = NULL;
aInfo->ai_next = NULL;
printf("\nCreata struttura addressinfo per nome simbolico host %s e servizio %s\n",
hostName, port );
// eseguo lookup host
int lookupResultCode = getaddrinfo( hostName, // nodo
argv[2], // servizio
aInfo, // informazioni per lookup
&lookupResults
);
// se ho codice diverso da zero allora sono in errore
if( lookupResultCode != 0 ){
printf( "\nRisultato lookup [%d] = %s\n", lookupResultCode,
gai_strerror(lookupResultCode) );
exit( EXIT_FAILURE );
}
// se sono qui ho effettuato il lookup, devo iterare su tutti i possibili
// risultati
struct addrinfo *currentResult;
for( currentResult = lookupResults; currentResult != NULL; currentResult = currentResult->ai_next ){
printf( "\n*** Risultato di lookup ***\n" );
printf( "\n\tNome canonico:\t%s", currentResult->ai_canonname );
printf( "\n\tLunghezza indirizzo:\t%d", currentResult->ai_addrlen );
// conversione a struttura socket address per internet
struct sockaddr_in *socketAddress = currentResult->ai_addr;
// stampa dei campi
printf( "\n\tPorta:\t%d", socketAddress->sin_port );
struct in_addr addressIP = socketAddress->sin_addr;
char* buffer = malloc( 24 * sizeof(char) );
inet_ntop( AF_INET, &addressIP, buffer, currentResult->ai_addrlen );
printf( "\n\tIndirizzo grezzo:\t%d", addressIP.s_addr );
printf( "\n\tIndirizzo tradotto:\t%s", buffer );
int i = 0;
int mask = 0xFF;
for( i = 0; i < 4; i++ ){
printf( "\n\tPezzo di indirizzo %d:\t%d",
i, ( (addressIP.s_addr) >> (8*i) ) & mask);
}
printf( "\n-----\n" );
}
}
Il programma, seppur abbastanza lungo per essere un esempio didattico, e' molto semplice: si vuole ricerca l'indirizzo IPv4 mediante lookup (del resolver) di un sito internet e del relativo servizio, per poi estrarre i singoli pezzi dell'indirizzo e suddividerli in byte. Per meglio comprendere si consideri la seguente invocazione:
$ ./net.exe www.kde.org 80
Creata struttura addressinfo per nome simbolico host www.kde.org e servizio 80
*** Risultato di lookup ***
Nome canonico: (null)
Lunghezza indirizzo: 16
Porta: 20480
Indirizzo grezzo: -94370770
Indirizzo tradotto: 46.4.96.250
Pezzo di indirizzo 0: 46
Pezzo di indirizzo 1: 4
Pezzo di indirizzo 2: 96
Pezzo di indirizzo 3: 250
-----
La parte interessante e' l'indirizzo grezzo: il valore riportato rappresenta 32 bit di informazione che identificano l'host www.kde.org. Tale indirizzo non e' facilmente memorizzabile da un umano e comunque ha una forma "strana" (e' perfino negativo!). L'indirizzo tradotto, quello in notazione dotted-quad, viene ottenuto mediante la funzione inet_ntop(..) che converte il numero unico di 32 bit in una stringa dotted-quad. Sarebbe possibile estrarre i singoli pezzi da 1 byte con una serie di "and" logici, come fa in effetti il programma a livello didattico. Tuttavia tale metodo non e' consigliato poiche' non tiene conto dell'ordinamento dei byte che dipende dalla architettura di sistema (little-endian, big-endian).
Ad ogni modo, a livello didattico, il programma preleva ogni singolo byte dell'indirizzo IPv4 e lo mette in "and" logico con 0xFF (255) al fine di estrarre ogni singolo valore della notazione dotted-quad.
Ed ecco svelato il mistero dietro alla notazione dotted-quad.
Nessun commento:
Posta un commento