11.9 IP-Adressen konvertieren, manipulieren und extrahieren
Bevor Sie noch tiefer in die Welt der Netzwerkprogrammierung einsteigen können, benötigen Sie noch das Wissen einiger Funktionen, die auf den vorherigen Seiten noch nicht oder ungenügend behandelt wurden.
11.9.1 inet_aton(), inet_pton() und inet_addr()
Mit den Funktionen inet_aton() und inet_addr() konvertieren Sie den String in der punktierten Dezimaldarstellung (z. B. »127.0.0.1«) in eine 32-Bit-Internet-Adresse. Die Funktion inet_addr() ist veraltet und wird deshalb hier nicht mehr behandelt. Die Syntax zu inet_aton():
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int inet_aton(const char *ptr, struct in_addr *inp);
Hiermit wird aus der punktierten Stringdarstellung ptr eine 32-Bit-Adresse konvertiert. Der Wert dieser 32-Bit-Adresse befindet sich anschließend in der Adresse der Struktur in_addr. Diese Struktur ist ja auch Teil der Struktur, die zur IP-Socket-Adresse verwendet wird. Hier nochmals die Struktur zur Erinnerung:
struct sockaddr_in {
/* Adressfamilie normalerweise AF_INET */
short int sin_family;
/* Port der Verbindung */
unsigned short int sin_port;
/* Adresse, zu der verbunden werden soll */
struct in_addr sin_addr;
/* Fuelldaten, um auf 14 Bytes zu kommen */
unsigned char sin_zero[8];
};
Die Struktur in_addr, die von vielen der folgenden Funktionen ebenfalls verwendet wird, ist in der Headerdatei <netinet/in.h> folgendermaßen definiert:
struct in_addr{
unsigned long int sin_addr;
}
Bei einem Fehler gibt die Funktion inet_aton() 0, ansonsten bei Erfolg einen Wert ungleich 0 zurück.
Zukunftsweisend ist hier noch die Funktion inet_pton(), die im Gegensatz zu inet_aton() auch noch andere Adressen als IPv4 wandelt:
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
int inet_pton(int af, const char *src, void *dst);
Für af geben Sie die Adressfamilie wie schon bei socket() an, für src den String der punktierten Darstellung und mit dst einen Zeiger auf die Zielstruktur, die je nach Adressfamilie variiert. In der Praxis:
struct in_addr addr;
inet_pton(AF_INET, "127.0.0.1", &addr);
11.9.2 inet_ntoa() und inet_ntop()
Soll im Gegenzug aus der 32-Bit-Darstellung der IP-Adresse wieder eine punktierte Darstellung zum String gemacht werden, steht Ihnen die Funktion inet_ntoa() zur Verfügung:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
char *inet_ntoa( struct in_addr in );
Damit wird die übergebene 32-Bit-Adresse als Parameter, die als network-byte-order vorliegen muss, in eine punktierte Dezimaldarstellung als String konvertiert. Der String wird als Rückgabewert der Funktionen in einem statischen Puffer abgelegt. Bei einem Fehler wird NULL zurückgegeben.
Die Funktion inet_ntoa() ist nicht thread-safe, da sie einen statischen Puffer verwendet! Daher – wieder die zukunftssicherere Alternative – inet_ntop():
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
const char *inet_ntop( int af, const void *src,
char *dst, socklen_t cnt );
Für af geben Sie wieder die Adressfamilie wie schon bei socket() an, für src die 32-Bit-Darstellung der IP-Adresse und mit dst einen Zeiger auf einen String, in dem der konvertierte Wert mit cnt Bytes kopiert wird. In der Praxis:
char buf[16];
...
inet_ntop(AF_INET, &addr, buf, 16);
11.9.3 inet_network()
Um aus einer IP-Adresse (punktierte Dezimaldarstellung in Form eines Strings) eine Netzwerknummer zu machen, können Sie die Funktion inet_network() verwenden:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
in_addr_t int inet_network( const char * ptr );
Damit konvertieren Sie die punktierte String-Dezimaldarstellung der IP-Adresse ptr in die Netzwerknummer. Diese Netzwerknummer wird bei Erfolg als Rückgabewert von inet_network() in host-byte-order zurückgegeben. Bei einem Fehler wird -1 zurückgegeben.
Netzwerknummer ist der Netzanteil einer IP-Adresse. Die IP-Adressen werden wiederum in eine IP-Netzklasse unterteilt. Dies ist eine Unterteilung in einen Netz- und einen Host-Anteil. Die Netzklasse ist abhängig von der Anzahl der Computer, die z. B. in einer Firma an das Internet angeschlossen sind. Generell werden in der Praxis die Klassen A, B und C verwendet. Die Klasse C teilt die Adresse in N.N.N.H (N – Netz, H – Host) und enthält so 255 Adressen. Mit der Klasse B sind 255 mal 255 Adressen möglich, weil zwei Byte für den Hostanteil verwendet werden (N.N.H.H). Und die Klasse A wird kaum noch verwendet, da sie mit 16581375 adressierbaren Computern (N.H.H.H) ein sehr großes Stück aus dem knappen Adressraum herausschneidet.
|
11.9.4 inet_netof()
Um aus einer nummerischen 32-Bit-IP-Adresse eine Netzwerknummer zu machen, können Sie die Funktion inet_netof() verwenden:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
in_addr_t int inet_netof( struct in_addr in );
Damit konvertieren Sie die nummerische 32-Bit-Darstellung der IP-Adresse, die als Parameter angegeben wird, in die Netzwerknummer. Diese Netzwerknummer wird bei Erfolg als Rückgabewert von inet_netof() in host-byte-order zurückgegeben. Bei einem Fehler wird -1 zurückgegeben.
11.9.5 inet_lnaof()
Um den lokalen Teil aus einer nummerischen 32-Bit-IP-Adresse zu extrahieren, steht Ihnen die Funktion inet_lnaof() zur Verfügung:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
in_addr_t inet_lnaof( struct in_addr in );
Damit ermitteln Sie die Adresse des lokalen Teils (z. B. 127.0.0.1 -> der lokale Teil = 0.0.0.1) des Rechners. Die Funktion gibt diesen Wert in Form eines 32-Bit-Wertes in host-byte-order zurück. Bei Fehler wird -1 zurückgegeben.
11.9.6 inet_makeaddr()
Um aus dem lokalen Teil eines Rechners und einer Netzwerknummer eine richtige nummerische IP-Adresse zu machen, können Sie die Funktion inet_makeaddr() verwenden:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
struct in_addr inet_makeaddr( int net, int host );
Damit wird aus der Netzwerknummer net und der Adresse des lokalen Rechnerteils (host) eine vollständige nummerische 32-Bit-IP-Adresse zurückgeliefert. Die Werte net und host müssen in host-byte-order übergeben werden.
Hierzu ein Listing mit allen Funktionen bei der Ausführung:
/* addr.c */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
static void ip_adressen (const char *ip_addr) {
struct in_addr ip;
char *ip_str;
if (inet_aton (ip_addr, &ip) == 0)
return;
printf ("\n *** Gesamtteil der IP-Adresse *** \n");
printf ("IP-Adresse (argv[1]) : %s\n",
ip_addr);
printf ("IP-Adresse als 32-Bit Wert - inet_aton() : %d\n",
ip.s_addr);
ip_str = inet_ntoa (ip);
if (ip_str == NULL)
return;
printf ("IP-Adresse String mit inet_ntoa() : %s\n",
ip_str);
}
static void ip_netzwerk (const char *ip_addr) {
struct in_addr ip, net_ip;
unsigned long int net, net_num;
if (inet_aton (ip_addr, &ip) == 0)
return;
net = inet_netof (ip);
if (net <= 0)
return;
/* Netzwerkteil */
printf ("\n *** Netzwerkteil der IP-Adresse *** \n");
printf ("Netzwerknummer der IP-Adresse mit "
"inet_netof() : %lu\n", net);
net_ip.s_addr = net_num = ntohl (inet_netof (ip) << 8);
printf ("--->%s", inet_ntoa (net_ip));
printf ("--> (als 32-Bit-Wert) : %ld\n", net_num);
net_ip = inet_makeaddr (htonl (net_num), 0);
printf ("inet_makeaddr()->(als 32-Bit-Wert) : %d\n",
net_ip.s_addr);
}
static void ip_lokal (const char *ip_addr) {
struct in_addr ip, lokal_ip;
unsigned long int lokal_num;
if (inet_aton (ip_addr, &ip) == 0)
return;
printf ("\n *** Lokaler Teil der IP-Adresse *** \n");
lokal_ip.s_addr = lokal_num = ntohl (inet_lnaof (ip));
printf ("--->%s", inet_ntoa (lokal_ip));
printf ("--> (als 32-Bit-Wert) : %ld\n", lokal_num);
lokal_ip = inet_makeaddr (0, htonl (lokal_num));
printf ("inet_makeaddr()->(als 32-Bit-Wert) : %d\n",
lokal_ip.s_addr);
}
static void ip_zusammen (const char *ip_addr) {
struct in_addr ip, lokal_ip, net_ip, zusammen_ip;
unsigned long int lokal_num, net_num;
if (inet_aton (ip_addr, &ip) == 0)
return;
printf ("\n *** Lokale Teile und Netzwerkteil "
"zusammensetzen *** \n");
lokal_ip.s_addr = lokal_num = ntohl (inet_lnaof (ip));
printf ("Lokaler Teil: ");
printf ("%20s = ", inet_ntoa (lokal_ip));
printf ("(als 32-Bit-Wert) : %ld\n", lokal_num);
printf ("Netzwerkteil: ");
net_ip.s_addr = net_num = ntohl (inet_netof (ip) << 8);
printf ("%20s = ", inet_ntoa (net_ip));
printf ("(als 32-Bit-Wert) : %ld\n", net_num);
zusammen_ip=inet_makeaddr( htonl (net_num),
htonl (lokal_num));
printf("Alles wieder mit inet_makeaddr zusammengefügt: ");
printf ("\n%s = %d\n", inet_ntoa (zusammen_ip),
zusammen_ip.s_addr);
}
int main (int argc, char **argv) {
char *ptr;
if (argc != 2)
printf ("Verwendung %s IP-Adresse\n", *argv);
else {
ptr = argv[1];
ip_adressen (ptr);
ip_netzwerk (ptr);
ip_lokal (ptr);
ip_zusammen (ptr);
}
return EXIT_SUCCESS;
}
Das Programm bei der Ausführung:
$ gcc -o addr addr.c
$ ./addr 213.131.254.130
*** Gesamtteil der IP-Adresse ***
IP-Adresse (argv[1]) : 213.131.254.130
IP-Adresse als 32-Bit Wert mit inet_aton() : 2197717973
IP-Adresse String mit inet_ntoa() : 213.131.254.130
*** Netzwerkteil der IP-Adresse ***
Netzwerknummer der IP-Adresse mit inet_netof() : 13992958
--->213.131.254.0--> (als 32-Bit-Wert) : 16679893
mit inet_makeaddr() --> (als 32-Bit-Wert) : 16679893
*** Lokaler Teil der IP-Adresse ***
--->0.0.0.130--> (als 32-Bit-Wert) : 2181038080
mit inet_makeaddr() --> (als 32-Bit-Wert) : 2181038080
*** Lokale Teile und Netzwerkteil zusammensetzen ***
Lokaler Teil: 0.0.0.130 = (als 32-Bit-Wert) : 2181038080
Netzwerkteil: 213.131.254.0 = (als 32-Bit-Wert) : 16679893
Alles wieder mit inet_makeaddr() zusammengefügt:
213.131.254.130 = 2197717973
|