Win32 Netzwerk-Setup
« | 28 Jan 2023 | »Besonders für “Lizenzen” hatte ich schon öfter den Auftrag, Hardware-Infos auszulesen. Sehr beliebt sind dafür MAC-Adressen. Aber auch für manche Server braucht man die Liste der aktuellen IP Adressen, damit man sich daran binden kann.
Leider hat Windows in den letzten 30 Jahren da einiges geändert und somit braucht man oft mehrere Schnittstellen. ————————————————————
Zu Zeiten von WinNT 4
war die Welt noch einfach.
Grundsätzlich sollte der User gar keine Details über das Netzwerk wissen,
sondern nur Laufwerke darüber verbinden und dann “transparent” mit anderen
Systemen im Netzwerk Daten austauschen.
Ob da jetzt ein NetBEUI,
IPX/SPX oder
TCP/IP dahinter
benutzt wurde, sollte niemanden interessieren.
Und dann kam das Internet und TCP/IP wurde DER Standard.
Und dann wurde es noch komplizierter:
- Wir erhielten mehrere IP’s pro physischen Adapter
- Dann tauchten virtuelle Netzwerkgeräte auf
- IPv6 kam auch noch dazu
- Und spätestens mit Hyper-V wurde ein Adapter in mehrere aufgeteilt.
Wir müssen heute also zuerst mal unterscheiden, ob wir Netzwerkgeräte oder Endknoten (wie IP Adressen) auflisten wollen. Und wegen möglicher virtualisieren kann durchaus eine MAC-Adresse auch mehrfach vorkommen.
Die NT APIs
Mit GetIfTable
kommt man bis ins Jahr 1998 zurück, als NT4 SP4 und
Windows 98 die API
eingeführt haben.
Sie liefert alle “Interfaces” als MIB_IFROW
zurück, die im System
installiert sind. Früher war das mal das eine IP-Interface, das an den
einen Netzwerkadapter gebunden war. Heute liefert die Funktion leider
eine Vielzahl von virtuellen und deaktivierten Schnittstellen, womit man
erst viele Flags und andere Kriterien auswerten muss, bis man die
relevanten Schnittstellen ausgefiltert bekommen hat.
Im Feld wszName
finden wir heute die Interface-GUID, mit der man bevorzugt
arbeiten sollte, wenn man die Infos mit anderen Schnittstellen abgleichen will.
Zu NT4 Zeiten gab es die GUID auf der Ebene noch nicht, sondern man musste
über den dwIndex
(Netzwerk-Interface-Index) das Gerät eindeutig
identifizieren.
Das bDescr
Feld gibt uns einen anzeigbaren Namen der Netzwerkschnittstelle
zurück und bPhysAddr
enthält die MAC-Adresse des verbundenen Adapters.
Die API GetIpAddrTable
listet alles in einer struct MIB_IPADDRTABLE
auf, was eine IP-Adresse hat
oder haben könnte.
Hier kann man eine Verbindung zu GetIfTable
über dwIndex
herstellen und
somit einen Eintrag der “Interface-Table” mit der “IP-Addr-Table” verknüpfen.
Windows 2000 (und teils Win98)
Mit GetAdaptersInfo
erhalten wir in Win2K und teils Win98 bereits eine Combo aus Adapter und IP
Adressen in der IP_ADAPTER_INFO
Struktur. Hier sind dann sogar Gateways
und DHCP Infos mit dabei, wie auch die gute alte MAC-Adresse.
Fast könnte man glauben, diese wäre die perfekte API, doch leider listet sie nur “aktivierte” Adapter mit IPs auf. Das reicht für Socket-Bindungen, aber MAC-Adressen für Lizenzen sind dann ein Problem. Außerdem fehlt der Support für IPv6, da es dieses Protokoll damals noch nicht gab.
Windows XP
XP brachte uns daher GetAdaptersAddresses,
welches uns auch IPv6 Daten in seinen IP_ADAPTER_ADDRESSES
Strukturen
liefert.
Hier wird es wieder kompliziert, wenn es um die Verknüpfung mit anderen APIs
geht. Der Interface-Index liegt hier nämlich entweder im Feld IfIndex
oder
in Ipv6IfIndex
.
Ich nutze die API daher nur für IPv6 Adressen und hole die anderen Daten
über GetAdaptersInfo
ab.
Von Windows Vista bis heute
Am Ende kam dann mit GetIfTable2
und der MIB_IF_TABLE2
ab Windows Vista eine aktualisierte Variante von
GetIfTable
auf den Markt, die uns mehr Flags und Details über die Hardware
liefert. So wissen wir, ob es ein WLAN oder Ethernet-Gerät ist, oder ob es nur
eine virtuelle Verbindungsbrücke zwischen zB. IPv4 und IPv6 ist.
Die klassischen NT-APIs liefern heute im schlimmsten Fall 60 Geräte, wie bei mir, wenn Hyper-V, WSL und Docker läuft, und dann weiß kein Mensch mehr, welches davon ein Adapter ist, über den eine lokale Anwendung ihre Daten hinausschicken würde.
Andere APIs
Eine hervorragende Alternative zu alle dem ist übrigens
WMI, denn
dort kann man sich die vielen APIs schenken und WMI-Queries absetzen und die
Ergebnisse einsammeln.
Ein paar interessante Queries sind:
Die WMI Objekte unterstützen Methoden wie Disable
, EnableStatic
EnableDHCP
oder SetGateways
und somit kann man auch gleich die
Netzwerkeinstellungen nach Belieben abändern.
Die COM API der Internet-Connection-Sharing Umgebung stellt auch ein paar Methoden bereit, um Netzwerkeinstellungen auszulesen. Ich habe allerdings stets nur das Interface INetConnection zum Ein- und Ausschalten eines Netzwerkadapters benutzt.
Fazit
Im GATE Projekt nutze ich alle nativen Win32 APIs, aber optional.
Auf einem modernen Host bekomme ich so also IPv6 Details und Infos, welche
Adapter zu streichen sind.
Und dann wird bis zur alten NT4-API alles aufgerufen, was da ist, um den
Datensatz anzureichern, der dann am Ende ausgegeben wird.
Ja, die Windows Netzwerk APIs sind kompliziert … aber sie bilden eben 30 Jahre Softwaregeschichte ab … und Geschichte ist immer auch ein bisschen kompliziert.