std.net.dhcp

DHCP-Client nach RFC 2131 — vollständige IP-Adressvergabe über UDP-Broadcast. Deckt den gesamten DORA-Prozess ab (Discover → Offer → Request → Acknowledge) und stellt Paket-Builder, Reply-Parser und High-Level-Lease-Funktion bereit.

import std.net.dhcp;
import std.alloc;

// Vollständigen Lease in einem Aufruf holen
var mac:    int64 := alloc(6);
var result: int64 := alloc(DHCP_RESULT_SIZE);
// mac mit 6 Byte Ethernet-Adresse befüllen ...
poke8(mac, 0xAA);  poke8(mac+1, 0xBB);  // ...

if (DhcpLease(mac, result) == 0) {
    var ip:    int64 := peek64(result + DHCP_RESULT_IP);
    var gw:    int64 := peek64(result + DHCP_RESULT_GW);
    var lease: int64 := peek64(result + DHCP_RESULT_LEASE);
}
free(result, DHCP_RESULT_SIZE);
free(mac, 6);

Berechtigung: Port 68 < 1024 — erfordert root oder CAP_NET_BIND_SERVICE.

Imports

  • std.net.socket
  • std.net.syscalls
  • std.net.types
  • std.alloc

Konstanten

Ports

Konstante Wert Bedeutung
DHCP_PORT_SERVER 67 UDP-Port des DHCP-Servers
DHCP_PORT_CLIENT 68 UDP-Port des DHCP-Clients

Operationscodes

Konstante Wert Bedeutung
DHCP_OP_REQUEST 1 BOOTREQUEST — Client→Server
DHCP_OP_REPLY 2 BOOTREPLY — Server→Client

DHCP-Nachrichtentypen (Option 53)

Konstante Wert Bedeutung
DHCP_MSG_DISCOVER 1 Client sucht DHCP-Server
DHCP_MSG_OFFER 2 Server bietet IP an
DHCP_MSG_REQUEST 3 Client fordert angebotene IP an
DHCP_MSG_DECLINE 4 Client lehnt angebotene IP ab
DHCP_MSG_ACK 5 Server bestätigt Lease
DHCP_MSG_NAK 6 Server verweigert Lease
DHCP_MSG_RELEASE 7 Client gibt IP frei
DHCP_MSG_INFORM 8 Client fragt Konfiguration ohne IP-Zuweisung

Options-Codes

Konstante Wert Bedeutung
DHCP_OPT_SUBNET 1 Subnet Mask
DHCP_OPT_ROUTER 3 Default Gateway
DHCP_OPT_DNS 6 DNS-Server (erster Eintrag wird gespeichert)
DHCP_OPT_HOSTNAME 12 Hostname (nur deklariert, nicht gesetzt)
DHCP_OPT_DOMAIN 15 Domain Name (nur angefordert, nicht geparst)
DHCP_OPT_REQIP 50 Requested IP Address
DHCP_OPT_LEASE 51 Lease-Zeit in Sekunden
DHCP_OPT_MSGTYPE 53 Nachrichtentyp
DHCP_OPT_SERVERID 54 Server Identifier (IP des DHCP-Servers)
DHCP_OPT_PARAMREQ 55 Parameter Request List
DHCP_OPT_PAD 0 Padding-Byte
DHCP_OPT_END 255 Ende der Options

Paket-Feldoffsets (RFC 2131 §2)

Konstante Offset Größe Inhalt
DHCP_OFFS_OP 0 1 Operationscode
DHCP_OFFS_HTYPE 1 1 Hardware-Typ (1 = Ethernet)
DHCP_OFFS_HLEN 2 1 Hardware-Adresslänge (6 für MAC)
DHCP_OFFS_HOPS 3 1 Relay-Agent-Hops
DHCP_OFFS_XID 4 4 Transaction ID (Big-Endian)
DHCP_OFFS_SECS 8 2 Sekunden seit Start
DHCP_OFFS_FLAGS 10 2 Flags (Bit 15 = Broadcast)
DHCP_OFFS_CIADDR 12 4 Client IP (bei Erneuerung)
DHCP_OFFS_YIADDR 16 4 Angebotene/zugewiesene IP
DHCP_OFFS_SIADDR 20 4 Nächster Server
DHCP_OFFS_GIADDR 24 4 Relay Agent IP
DHCP_OFFS_CHADDR 28 16 Client-Hardware-Adresse (MAC in Byte 0–5)
DHCP_OFFS_SNAME 44 64 Server-Hostname
DHCP_OFFS_FILE 108 128 Boot-Dateiname
DHCP_OFFS_COOKIE 236 4 Magic Cookie (0x63825363)
DHCP_OFFS_OPTIONS 240 Beginn der Options
DHCP_MIN_LEN 300 Mindestgröße (BOOTP-kompatibel)

Sonstiges

Konstante Wert Bedeutung
DHCP_FLAG_BROADCAST 128 (0x80) Broadcast-Bit (Byte 10, Bit 7)
DHCP_MAGIC_B0..B3 99,130,83,99 Magic Cookie 0x63825363
DHCP_HTYPE_ETHER 1 Hardware-Typ Ethernet

Result-Struct (DHCP_RESULT_SIZE = 72 Bytes)

Wird vom Caller alloziert und mit Nullen initialisiert. DhcpParseReply, DhcpDiscover, DhcpRequest und DhcpLease schreiben hinein.

Alle IP-Adressen sind im selben gepackten Format wie IPPack() aus std.net.types gespeichert (Big-Endian uint32 in int64).

Offset-Konstante Offset Inhalt
DHCP_RESULT_IP 0 Zugewiesene IP-Adresse
DHCP_RESULT_MASK 8 Subnetzmaske
DHCP_RESULT_GW 16 Default Gateway
DHCP_RESULT_DNS 24 Primärer DNS-Server (erster aus Option 6)
DHCP_RESULT_LEASE 32 Lease-Zeit in Sekunden
DHCP_RESULT_SERVER 40 DHCP-Server-IP (Option 54)
DHCP_RESULT_XID 48 Transaction ID
DHCP_RESULT_TYPE 56 Nachrichtentyp (2=OFFER, 5=ACK, 6=NAK)
DHCP_RESULT_OK 64 1 = Lease erfolgreich erhalten

Funktionen

Paket-Builder

Signatur Beschreibung
DhcpBuildDiscover(buf: int64, mac: int64, xid: int64): int64 Baut DHCPDISCOVER-Paket in buf (≥ DHCP_MIN_LEN Bytes). mac = Zeiger auf 6-Byte-MAC. Broadcast-Flag gesetzt; Parameter Request List: Subnet, Router, DNS, Domain. Gibt DHCP_MIN_LEN zurück.
DhcpBuildRequest(buf: int64, mac: int64, xid: int64, offeredIP: int64, serverIP: int64): int64 Baut DHCPREQUEST-Paket. offeredIP und serverIP aus dem vorherigen OFFER übernommen (Option 50 + 54 werden gesetzt). Gibt DHCP_MIN_LEN zurück.

Reply-Parser

Signatur Beschreibung
DhcpParseReply(buf: int64, len: int64, result: int64): void Parst DHCP-Server-Antwort (OFFER oder ACK). Prüft OP=REPLY und Magic Cookie. Setzt DHCP_RESULT_OK=1 bei OFFER oder ACK; 0 bei NAK, ungültigem Paket oder zu kurzem Puffer. Füllt IP, Mask, GW, DNS, Lease, Server, Type.

High-Level Lease-Funktionen

Signatur Beschreibung
DhcpDiscover(mac: int64, xid: int64, result: int64): int64 Sendet DHCPDISCOVER (UDP-Broadcast) und wartet bis zu 5 Sekunden auf DHCPOFFER. Gibt 0 zurück wenn OFFER erhalten, -1 bei Fehler oder Timeout.
DhcpRequest(mac: int64, xid: int64, result: int64): int64 Sendet DHCPREQUEST (liest offeredIP und serverIP aus result) und wartet bis zu 5 Sekunden auf DHCPACK. Gibt 0 nur zurück wenn DHCP_RESULT_TYPE = DHCP_MSG_ACK.
DhcpLease(mac: int64, result: int64): int64 Vollständiger DORA-Prozess in einem Aufruf: Discover → Offer → Request → Acknowledge. XID wird aus den ersten 4 MAC-Bytes abgeleitet. Gibt 0 bei erfolgreichem Lease, -1 bei Fehler zurück.

DORA-Ablauf

Client                          Server (255.255.255.255:67)
   |                                 |
   |── DHCPDISCOVER (Broadcast) ────>|  xid = MAC[0..3]
   |<─ DHCPOFFER ────────────────────|  yiaddr=192.168.1.100, srv=192.168.1.1
   |                                 |
   |── DHCPREQUEST (Broadcast) ─────>|  opt50=192.168.1.100, opt54=192.168.1.1
   |<─ DHCPACK ──────────────────────|  Lease bestätigt, Lease-Zeit: 43200s

DhcpLease() führt den gesamten Ablauf durch. DhcpDiscover() und DhcpRequest() erlauben manuelle Steuerung (z. B. für Fehlerbehandlung oder Logging zwischen den Schritten).


Codebeispiel — Manueller DORA-Ablauf

import std.net.dhcp;
import std.net.types;
import std.alloc;

fn acquireLease(mac: int64): int64 {
    var result: int64 := alloc(DHCP_RESULT_SIZE);
    var xid:    int64 := peek8(mac);
    xid := (xid << 8) | peek8(mac + 1);
    xid := (xid << 8) | peek8(mac + 2);
    xid := (xid << 8) | peek8(mac + 3);

    if (DhcpDiscover(mac, xid, result) < 0) {
        free(result, DHCP_RESULT_SIZE);
        return 0 - 1;
    }

    var offeredIP: int64 := peek64(result + DHCP_RESULT_IP);
    var srvIP:     int64 := peek64(result + DHCP_RESULT_SERVER);
    // Hier könnte Validierung des OFFER stattfinden ...

    if (DhcpRequest(mac, xid, result) < 0) {
        free(result, DHCP_RESULT_SIZE);
        return 0 - 1;
    }

    var ip:    int64 := peek64(result + DHCP_RESULT_IP);
    var mask:  int64 := peek64(result + DHCP_RESULT_MASK);
    var gw:    int64 := peek64(result + DHCP_RESULT_GW);
    var dns:   int64 := peek64(result + DHCP_RESULT_DNS);
    var lease: int64 := peek64(result + DHCP_RESULT_LEASE);

    // IP-Adresse z. B. an Netzwerk-Interface binden ...
    // Lease-Erneuerung nach lease/2 Sekunden nötig

    free(result, DHCP_RESULT_SIZE);
    return 0;
}


Hinweise

  • Berechtigung: DhcpDiscover und DhcpRequest binden Port 68 — erfordert root oder CAP_NET_BIND_SERVICE. Auf Linux genügt: setcap cap_net_bind_service+ep ./programm.
  • IP-Format: Alle IP-Adressen im Result-Struct verwenden das IPPack-Format aus std.net.types (Big-Endian uint32 in int64). Zum Anzeigen: IpToStr() verwenden.
  • Timeout: DhcpDiscover und DhcpRequest warten je maximal 5 Sekunden auf eine Antwort (SocketCanRead(fd, 5000)). Kein automatischer Retry.
  • Kein Lease-Renewal: Diese Unit macht keine automatische Lease-Erneuerung. Die Anwendung muss nach lease/2 Sekunden DhcpLease erneut aufrufen.
  • XID: DhcpLease leitet die Transaction ID aus den ersten 4 MAC-Bytes ab. Bei mehreren gleichzeitigen Clients mit ähnlichen MACs kann es zu XID-Kollisionen kommen — in diesem Fall DhcpDiscover/DhcpRequest direkt mit einer zufälligen XID verwenden.
  • DNS: Nur der erste DNS-Server (Byte 0–3 von Option 6) wird gespeichert. Mehrere DNS-Server werden ignoriert.
  • BOOTP-Kompatibilität: Pakete sind mindestens 300 Bytes lang (DHCP_MIN_LEN) für ältere BOOTP-Server.

Quelldatei

Unit Datei
std.net.dhcp std/net/dhcp.lyx

Letzte Aktualisierung: 2026-06-17