Ist ein PC mit dem Namen "Beispiel" mit dem Netzwerk (LAN) verbunden, das Sie gerade verwenden? Wenn Sie eine temporäre virtuelle Maschine erstellen, können Sie eine Maschine mit einem Namen wie foo oder hoge erstellen, aber ich glaube nicht, dass Sie normalerweise diesen Computernamen verwenden. Gibt es auch eine Definition für den Namen "Beispiel" in "/ etc / hosts"? Wenn beispielsweise "127.0.0.1 Beispiel" angezeigt wird, sollte das Ausführen von "Ping-Beispiel" das Ping-Ergebnis von Ihrem Computer zurückgeben.
Von nun an gibt es keinen Host mit dem Namen "example", es gibt keine solche Definition in "/ etc / hosts", und das Ausführen von "ping example" führt zu "ping: unknown host example". Wir gehen davon aus, dass es angezeigt wird.
Die Suche nach einer IP-Adresse aus einem Hostnamen wird als Namensauflösung bezeichnet. Typische Beispiele sind "Hosts-Datei" und "DNS-Resolver". Was zu kontaktieren ist, wird automatisch bestimmt. Es wird von einer Funktion namens nsswitch (Name Service Switch) bereitgestellt. Schauen wir uns zunächst diese Konfigurationsdatei an. Versuchen Sie, / etc / nsswitch.conf
anzuzeigen.
soramimi@alice:~$ cat /etc/nsswitch.conf
# /etc/nsswitch.conf
#
# Example configuration of GNU Name Service Switch functionality.
# If you have the `glibc-doc-reference' and `info' packages installed, try:
# `info libc "Name Service Switch"' for information about this file.
passwd: compat
group: compat
shadow: compat
gshadow: files
hosts: files mdns4_minimal [NOTFOUND=return] dns
networks: files
protocols: db files
services: db files
ethers: db files
rpc: db files
netgroup: nis
In der Mitte gibt es eine Definition von "Hosts:", die mit "Dateien" beginnt. Es folgen "mdns4" oder "mdns4_minimal" und dann "dns". Wenn Sie Samba installiert haben, können Sie auch "Gewinne" haben.
Die führenden "Dateien" geben an, dass zuerst nach der Definition "/ etc / hosts" gesucht werden soll. Das "mdns" -System ist je nach Betriebssystemkonfiguration möglicherweise nicht verfügbar, aber es scheint, dass es viele Fälle gibt, in denen es in neueren Betriebssystemen als Standard verwendet werden kann. Dies wird als mDNS (Multicast DNS) bezeichnet, eine Standardfunktion zur Namensauflösung in macOS. Selbst unter Windows können Sie es verwenden, indem Sie "Bonjour for Windows" von Apple installieren. Es scheint, dass Windows 10 mDNS standardmäßig unterstützt. Wenn es also richtig eingestellt ist, ping [Hostname] Wenn Sie es wie .local
ausführen, ist die Namensauflösung erfolgreich und Sie sehen das Ergebnis des Pings. Das endgültige dns
ist eine Spezifikation, die den DNS-Server nach der Auflösung von Internetnamen abfragt.
Wenn der Hostname und die IP-Adresse vorbestimmt sind, ist es am einfachsten und gebräuchlichsten, sie in "/ etc / hosts" zu definieren. Wenn Sie die Namensauflösung dynamisch von einem Programm in einem anderen Dateiformat als Hosts oder einer Datenbank durchführen möchten, können Sie eine eigene Namensauflösungsbibliothek erstellen und diese nach Belieben in nsswitch.conf
registrieren.
In diesem Artikel entwickeln wir eine Namensauflösungsbibliothek in C-Sprache. Die Entität ist ein gemeinsam genutztes Objekt.
Es ist keine Übertreibung zu sagen, dass die Namensauflösungsfunktion die Grundlage für den Betriebssystembetrieb ist. Daher sind Root-Rechte erforderlich, um sie in das Betriebssystem zu integrieren. Wenn das Programm fehlerhaft ist, kann dies in einigen Fällen eine schwerwiegende Sicherheitslücke darstellen. Bitte seien Sie dort vorsichtig.
Das gesamte Programm einschließlich Makefile wird im folgenden Repository abgelegt.
https://github.com/soramimi/libnss-example
Es gibt nur zwei Funktionen in einer Quelldatei in C-Sprache. Die zweite Funktion ruft nur die erste Funktion auf, sodass es effektiv nur eine Funktion gibt.
main.c
#include <string.h>
#include <nss.h>
#include <netdb.h>
#include <stdlib.h>
#include <errno.h>
#include <arpa/inet.h>
#define ALIGN(idx) do { \
if (idx % sizeof(void*)) \
idx += (sizeof(void*) - idx % sizeof(void*)); /* Align on 32 bit boundary */ \
} while(0)
enum nss_status _nss_example_gethostbyname_r(const char *name, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop)
{
size_t idx, astart;
if (strcmp(name, "example") == 0) {
char const *host = "127.0.0.1";
*(char**)buffer = NULL;
result->h_aliases = (char**) buffer;
idx = sizeof(char*);
strcpy(buffer + idx, name);
result->h_name = buffer + idx;
idx += strlen(name) + 1;
ALIGN(idx);
result->h_addrtype = AF_INET;
result->h_length = sizeof(uint32_t);
struct in_addr addr;
inet_pton(AF_INET, host, &addr);
astart = idx;
memcpy(buffer+astart, &addr.s_addr, sizeof(uint32_t));
idx += sizeof(uint32_t);
result->h_addr_list = (char**)(buffer + idx);
result->h_addr_list[0] = buffer + astart;
result->h_addr_list[1] = NULL;
return NSS_STATUS_SUCCESS;
}
*errnop = EINVAL;
*h_errnop = NO_RECOVERY;
return NSS_STATUS_UNAVAIL;
}
enum nss_status _nss_example_gethostbyname2_r(const char *name, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop)
{
if (af != AF_INET) {
*errnop = EAGAIN;
*h_errnop = NO_RECOVERY;
return NSS_STATUS_TRYAGAIN;
} else {
return _nss_example_gethostbyname_r(name, result, buffer, buflen, errnop, h_errnop);
}
}
Alles, was es tut, ist "127.0.0.1" als Ergebnis zurückzugeben, wenn der Abfragename "Beispiel" ist, das war's. Auf den ersten Blick scheint der Prozess des Speicherns der Ergebnisse in einer Struktur, die nsswitch eigen ist, mühsam zu sein, aber dieser Teil ist nur ein vollständiger Streich der Leistungen unserer Vorgänger. Das ursprüngliche Programm, auf das ich mich bezog, ist this.
Kompilieren.
soramimi@alice:~/develop/libnss-example$ make
gcc -g -O2 -Wall -Wpointer-arith -fPIC -c -o main.o main.c
gcc -g -O2 -Wall -Wpointer-arith -shared -Wl,-soname,libnss_example.so.2 -Wl,-z,defs -o libnss_example.so.2 main.o
Ich kompiliere main.c
, um libnss_example.so.2
zu erstellen. Da es sich um ein gemeinsam genutztes Objekt handelt, hat es die Erweiterung ".so". Stellen Sie sich die letzte ".2" als eine Art API-Version vor. Andernfalls funktioniert es nicht. Fügen Sie daher am Ende ".2" hinzu.
Dann installieren Sie es.
soramimi@alice:~/develop/libnss-example$ sudo make install
install -m755 -d /usr/lib/
install -m644 libnss_example.so.2 /usr/lib/libnss_example.so.2
Ich kopiere es einfach in / usr / lib /
.
Bearbeiten Sie / etc / nsswitch.conf
. Fügen Sie am Ende der Definition von "Hosts" "Beispiel" hinzu: "und fertig.
...
hosts: files mdns4_minimal [NOTFOUND=return] dns example
...
Führen Sie einen Ping durch und überprüfen Sie, ob das Ergebnis zurückgegeben wird.
soramimi@alice:~$ ping example
PING example (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.034 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.033 ms
64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=0.029 ms
Wenn Sie eine eigene Namensauflösungsbibliothek erstellen möchten, z. B. "libnss_hogehoge.so.2" anstelle von "libnss_example.so.2", dann sind alle "Beispiele" in "main.c" und "Makefile" enthalten Ersetzen Sie durch "hogehoge". Die beiden Funktionsnamen sind auch "_nss_hogehoge_gethostbyname_r" bzw. "_nss_hogehoge_gethostbyname2_r". Wenn dann eine IP-Adresse vorhanden ist, um auf den von der Funktion empfangenen Namen zu antworten, setzen Sie die Adresse in struct in_addr addr, schreiben Sie sie in die Struktur und geben Sie NSS_STATUS_SUCCESS zurück.
Fügen Sie nach dem Kompilieren und Installieren den Namen der neu erstellten Bibliothek zur Definition von "hosts:" in "/ etc / nsswitch.conf" hinzu.
Recommended Posts