Milan Stephan
Fotografie & IT

Zurück zur SP2 Übersicht

dns.c

#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>

int main(int argc, char **argv) {

	if (argc != 2) {
		fprintf(stderr, "Syntax: %s <hostname>\n", argv[0]);
		exit(EXIT_FAILURE);
	}
	char *hostname = argv[1];


	struct addrinfo hints = {
		.ai_socktype = SOCK_STREAM, // Zum Durchreichen an socket(2)

		.ai_family = AF_UNSPEC,     // IPv4 und IPv6 (und ggf. andere, die passen)
		.ai_flags = AI_ADDRCONFIG,  // Einschränken auf das, was lokal funktioniert

		// Alle anderen Felder werden durch das "," nach dem letzten Eintrag implizit genullt
	};


	struct addrinfo *head;
	getaddrinfo(hostname, "80", &hints, &head);
	// Domain-Name ---^    ^     ^       ^-- Verkettete Liste, die die Ergebnisse
	//                     |     |           der DNS-Abfrage enthält. Der Speicher
	//                     |     |           muss später wieder freigegeben werden!
	//                     |     |
	//                     |     +-- Suchkriterien (ai_family, ai_flags)
	//                     |
	//                     +-- Nur fuer connect(2) benötigt. Der Port wird in
	//                         jedes Element der Ergebnisliste geschrieben.


	struct addrinfo *curr;
	for (curr = head; curr != NULL; curr = curr->ai_next) {

		// Der Code in der Schleife ist zur Ausgabe der IP-Adressen wichtig
		// und hat nichts mit der eigentlichen Aufgabe zu tun. Wenn also
		// nicht ganz klar ist, was hier passiert, ist das halb so wild. ;)
		char buffer[64];
		void *tmp;

		switch (curr->ai_addr->sa_family) {

			case AF_INET:
				tmp = &((struct sockaddr_in*) curr->ai_addr)->sin_addr;
				printf("IPv4 address: %s\n", inet_ntop(AF_INET, tmp, (char * restrict) &buffer, 64));
				break;

			case AF_INET6:
				tmp = &((struct sockaddr_in6*) curr->ai_addr)->sin6_addr;
				printf("IPv6 address: %s\n", inet_ntop(AF_INET6, tmp, (char * restrict) &buffer, 64));
				break;

			default:
				printf("Neither IPv4 nor IPv6.\n");
		}

	}

	// Freigeben des Speichers der verketteten Liste
	freeaddrinfo(head);
}