diff --git a/examples/DhcpCustomHostname/DhcpCustomHostname.ino b/examples/DhcpCustomHostname/DhcpCustomHostname.ino new file mode 100644 index 00000000..53977e60 --- /dev/null +++ b/examples/DhcpCustomHostname/DhcpCustomHostname.ino @@ -0,0 +1,95 @@ +/* + DHCP with custom hostname + + This sketch uses the DHCP extensions to the Ethernet library + to get an IP address via DHCP and print the address obtained. + using an Arduino WIZnet Ethernet shield. + + It demonstrates how to set a custom hostname for the DHCP request. + + Circuit: + Ethernet shield attached to pins 10, 11, 12, 13 + + created 14 December 2025 + by Dmytro Lahoza + */ + +#include +#include + +// Enter a MAC address for your controller below. +// Newer Ethernet shields have a MAC address printed on a sticker on the shield +byte mac[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED +}; + +void setup() { + // You can use Ethernet.init(pin) to configure the CS pin + //Ethernet.init(10); // Most Arduino shields + //Ethernet.init(5); // MKR ETH Shield + //Ethernet.init(0); // Teensy 2.0 + //Ethernet.init(20); // Teensy++ 2.0 + //Ethernet.init(15); // ESP8266 with Adafruit FeatherWing Ethernet + //Ethernet.init(33); // ESP32 with Adafruit FeatherWing Ethernet + + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + // Set the hostname for the DHCP request + Ethernet.setHostname("arduino-ethernet"); + + // start the Ethernet connection: + Serial.println("Initialize Ethernet with DHCP:"); + if (Ethernet.begin(mac) == 0) { + Serial.println("Failed to configure Ethernet using DHCP"); + if (Ethernet.hardwareStatus() == EthernetNoHardware) { + Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :("); + } else if (Ethernet.linkStatus() == LinkOFF) { + Serial.println("Ethernet cable is not connected."); + } + // no point in carrying on, so do nothing forevermore: + while (true) { + delay(1); + } + } + // print your local IP address: + Serial.print("My IP address: "); + Serial.println(Ethernet.localIP()); +} + +void loop() { + switch (Ethernet.maintain()) { + case 1: + //renewed fail + Serial.println("Error: renewed fail"); + break; + + case 2: + //renewed success + Serial.println("Renewed success"); + //print your local IP address: + Serial.print("My IP address: "); + Serial.println(Ethernet.localIP()); + break; + + case 3: + //rebind fail + Serial.println("Error: rebind fail"); + break; + + case 4: + //rebind success + Serial.println("Rebind success"); + //print your local IP address: + Serial.print("My IP address: "); + Serial.println(Ethernet.localIP()); + break; + + default: + //nothing happened + break; + } +} diff --git a/src/Dhcp.cpp b/src/Dhcp.cpp index 2bfd584b..69148c60 100644 --- a/src/Dhcp.cpp +++ b/src/Dhcp.cpp @@ -116,10 +116,15 @@ void DhcpClass::presend_DHCP() { } +void DhcpClass::setCustomHostname(const char* name) +{ + _dhcpHostname = name; +} + void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed) { - uint8_t buffer[32]; - memset(buffer, 0, 32); + uint8_t buffer[64]; + memset(buffer, 0, 64); IPAddress dest_addr(255, 255, 255, 255); // Broadcast address if (_dhcpUdpSocket.beginPacket(dest_addr, DHCP_SERVER_PORT) == -1) { @@ -153,14 +158,14 @@ void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed) //put data in W5100 transmit buffer _dhcpUdpSocket.write(buffer, 28); - memset(buffer, 0, 32); // clear local buffer + memset(buffer, 0, 64); // clear local buffer memcpy(buffer, _dhcpMacAddr, 6); // chaddr //put data in W5100 transmit buffer _dhcpUdpSocket.write(buffer, 16); - memset(buffer, 0, 32); // clear local buffer + memset(buffer, 0, 64); // clear local buffer // leave zeroed out for sname && file // put in W5100 transmit buffer x 6 (192 bytes) @@ -187,16 +192,18 @@ void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed) memcpy(buffer + 10, _dhcpMacAddr, 6); // OPT - host name + const char* hostname = _dhcpHostname ? _dhcpHostname : HOST_NAME; + size_t hostnameLen = strlen(hostname); buffer[16] = hostName; - buffer[17] = strlen(HOST_NAME) + 6; // length of hostname + last 3 bytes of mac address - strcpy((char*)&(buffer[18]), HOST_NAME); + buffer[17] = hostnameLen + 6; // length of hostname + last 3 bytes of mac address + strcpy((char*)&(buffer[18]), hostname); - printByte((char*)&(buffer[24]), _dhcpMacAddr[3]); - printByte((char*)&(buffer[26]), _dhcpMacAddr[4]); - printByte((char*)&(buffer[28]), _dhcpMacAddr[5]); + printByte((char*)&(buffer[18 + hostnameLen]), _dhcpMacAddr[3]); + printByte((char*)&(buffer[18 + hostnameLen + 2]), _dhcpMacAddr[4]); + printByte((char*)&(buffer[18 + hostnameLen + 4]), _dhcpMacAddr[5]); //put data in W5100 transmit buffer - _dhcpUdpSocket.write(buffer, 30); + _dhcpUdpSocket.write(buffer, 18 + hostnameLen + 6); if (messageType == DHCP_REQUEST) { buffer[0] = dhcpRequestedIPaddr; diff --git a/src/Ethernet.cpp b/src/Ethernet.cpp index 8d9ce7fd..4d1a201f 100644 --- a/src/Ethernet.cpp +++ b/src/Ethernet.cpp @@ -25,11 +25,15 @@ IPAddress EthernetClass::_dnsServerAddress; DhcpClass* EthernetClass::_dhcp = NULL; +char EthernetClass::_hostname[32] = {0}; int EthernetClass::begin(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) { static DhcpClass s_dhcp; _dhcp = &s_dhcp; + if (_hostname[0] != 0) { + _dhcp->setCustomHostname(_hostname); + } // Initialise the basic info if (W5100.init() == 0) return 0; @@ -178,6 +182,16 @@ IPAddress EthernetClass::gatewayIP() return ret; } +void EthernetClass::setHostname(const char* hostname) +{ + if (strlen(hostname) < 32) { + strcpy(_hostname, hostname); + if (_dhcp) { + _dhcp->setCustomHostname(_hostname); + } + } +} + void EthernetClass::setMACAddress(const uint8_t *mac_address) { SPI.beginTransaction(SPI_ETHERNET_SETTINGS); diff --git a/src/Ethernet.h b/src/Ethernet.h index 0045de88..3c916a09 100644 --- a/src/Ethernet.h +++ b/src/Ethernet.h @@ -75,6 +75,7 @@ class EthernetClass { private: static IPAddress _dnsServerAddress; static DhcpClass* _dhcp; + static char _hostname[32]; public: // Initialise the Ethernet shield to use the provided MAC address and // gain the rest of the configuration through DHCP. @@ -97,6 +98,7 @@ class EthernetClass { static IPAddress gatewayIP(); static IPAddress dnsServerIP() { return _dnsServerAddress; } + void setHostname(const char* hostname); void setMACAddress(const uint8_t *mac_address); void setLocalIP(const IPAddress local_ip); void setSubnetMask(const IPAddress subnet); @@ -297,6 +299,7 @@ class DhcpClass { unsigned long _lastCheckLeaseMillis; uint8_t _dhcp_state; EthernetUDP _dhcpUdpSocket; + const char *_dhcpHostname = NULL; int request_DHCP_lease(); void reset_DHCP_lease(); @@ -311,6 +314,7 @@ class DhcpClass { IPAddress getGatewayIp(); IPAddress getDhcpServerIp(); IPAddress getDnsServerIp(); + void setCustomHostname(const char* name); int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); int checkLease();