From 6ad334a1a14620b964776e5e68a023afc61cbaad Mon Sep 17 00:00:00 2001 From: HeAtNet Date: Sun, 28 May 2023 10:31:33 +0200 Subject: [PATCH 1/4] create option for setting and getting the hostname --- docs/api.md | 77 ++++++++++++++++++++++++++++ examples/SetHostName/SetHostName.ino | 61 ++++++++++++++++++++++ library.properties | 2 +- src/Dhcp.cpp | 18 +++---- src/Dhcp.h | 1 - src/Ethernet.cpp | 35 ++++++++++++- src/Ethernet.h | 11 +++- 7 files changed, 192 insertions(+), 13 deletions(-) create mode 100644 examples/SetHostName/SetHostName.ino diff --git a/docs/api.md b/docs/api.md index 76265c82..c8117e06 100644 --- a/docs/api.md +++ b/docs/api.md @@ -473,6 +473,83 @@ void setup() { void loop () {} ``` +### `Ethernet.setHostName()` + +#### Description + +Set the hostname of the device. This is used in DHCP requests and responses. + + +#### Syntax + +``` +Ethernet.setHostName(hostName) + +``` + +#### Parameters +- hostName: the hostname of the device (const char*) + +#### Returns +Nothing + +#### Example + +``` +#include +#include + +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; +char hostName[] = "NameOfTheDevice"; + +void setup() { + Ethernet.setHostName(hostName); + Ethernet.begin(mac); +} + +void loop () {} +``` + +### `Ethernet.getHostName()` + +#### Description + +Get the hostname of the device. This is used in DHCP requests and responses. + + +#### Syntax + +``` +Ethernet.getHostName() + +``` + +#### Parameters +none + +#### Returns +- hostName: the hostname of the device (const char*) + +#### Example + +``` +#include +#include + +byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; + +void setup() { + Ethernet.begin(mac); + const char* hostName = Ethernet.getHostName(); + + Serial.begin(9600); + Serial.print("Host name: "); + Serial.println(hostName); +} + +void loop () {} +``` + ### `Ethernet.setGatewayIP()` #### Description diff --git a/examples/SetHostName/SetHostName.ino b/examples/SetHostName/SetHostName.ino new file mode 100644 index 00000000..5eb08c23 --- /dev/null +++ b/examples/SetHostName/SetHostName.ino @@ -0,0 +1,61 @@ +/* + Set Host Name + + This example shows you how to set the host name with the Ethernet library. + + Circuit: + * Ethernet shield attached to pins 10, 11, 12, 13 + + created 28 May 2023 + by Attila Herczog +*/ + +#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 }; + +// Host name to use +char hostName[] = "ExampleHostName"; + +void setup() +{ + // 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 + } + Serial.println("Host Name Example"); + + // Set the Host Name + // Call this function before Ethernet.begin() to set your host name. + Ethernet.setHostName(hostName); + + // Start the Ethernet connection and the server: + Ethernet.begin(mac); + + // Check for Ethernet hardware present + if (Ethernet.hardwareStatus() == EthernetNoHardware) + { + Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :("); + while (true) + { + delay(1); // do nothing, no point running without Ethernet hardware + } + } + if (Ethernet.linkStatus() == LinkOFF) + { + Serial.println("Ethernet cable is not connected."); + } + + Serial.print("My IP is: "); + Serial.println(Ethernet.localIP()); + Serial.print("My host name is: "); + Serial.println(Ethernet.getHostName()); + Serial.println("You can now check your router's DHCP table to see the assigned host name."); +} + +void loop() {} diff --git a/library.properties b/library.properties index f3f36166..0c5d9a9a 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Ethernet -version=2.0.2 +version=2.0.3 author=Various (see AUTHORS file for details) maintainer=Arduino sentence=Enables network connection (local and Internet) using the Arduino Ethernet Board or Shield. diff --git a/src/Dhcp.cpp b/src/Dhcp.cpp index 2bfd584b..aa12c721 100644 --- a/src/Dhcp.cpp +++ b/src/Dhcp.cpp @@ -6,13 +6,14 @@ #include "Dhcp.h" #include "utility/w5100.h" -int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) +int DhcpClass::beginWithDHCP(uint8_t *mac, const char *hostName, unsigned long timeout, unsigned long responseTimeout) { _dhcpLeaseTime=0; _dhcpT1=0; _dhcpT2=0; _timeout = timeout; _responseTimeout = responseTimeout; + _dhcpHostName = hostName; // zero out _dhcpMacAddr memset(_dhcpMacAddr, 0, 6); @@ -186,17 +187,16 @@ void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed) buffer[9] = 0x01; memcpy(buffer + 10, _dhcpMacAddr, 6); - // OPT - host name - buffer[16] = hostName; - buffer[17] = strlen(HOST_NAME) + 6; // length of hostname + last 3 bytes of mac address - strcpy((char*)&(buffer[18]), HOST_NAME); + _dhcpUdpSocket.write(buffer, 16); - printByte((char*)&(buffer[24]), _dhcpMacAddr[3]); - printByte((char*)&(buffer[26]), _dhcpMacAddr[4]); - printByte((char*)&(buffer[28]), _dhcpMacAddr[5]); + // OPT - host name + buffer[0] = hostName; + uint8_t hostNameLength = strlen(_dhcpHostName); + buffer[1] = hostNameLength; + strcpy((char*)&(buffer[2]), _dhcpHostName); //put data in W5100 transmit buffer - _dhcpUdpSocket.write(buffer, 30); + _dhcpUdpSocket.write(buffer, hostNameLength + 2); if (messageType == DHCP_REQUEST) { buffer[0] = dhcpRequestedIPaddr; diff --git a/src/Dhcp.h b/src/Dhcp.h index 43ec4f85..1b3ed2a3 100644 --- a/src/Dhcp.h +++ b/src/Dhcp.h @@ -42,7 +42,6 @@ #define MAGIC_COOKIE 0x63825363 #define MAX_DHCP_OPT 16 -#define HOST_NAME "WIZnet" #define DEFAULT_LEASE (900) //default lease time in seconds #define DHCP_CHECK_NONE (0) diff --git a/src/Ethernet.cpp b/src/Ethernet.cpp index 8d9ce7fd..9578f604 100644 --- a/src/Ethernet.cpp +++ b/src/Ethernet.cpp @@ -25,6 +25,8 @@ IPAddress EthernetClass::_dnsServerAddress; DhcpClass* EthernetClass::_dhcp = NULL; +bool EthernetClass::_manualHostName = false; +char EthernetClass::_hostName[HOST_NAME_MAX_LEN] = ""; int EthernetClass::begin(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) { @@ -38,8 +40,13 @@ int EthernetClass::begin(uint8_t *mac, unsigned long timeout, unsigned long resp W5100.setIPAddress(IPAddress(0,0,0,0).raw_address()); SPI.endTransaction(); + // Generate a default host name based on the MAC address if not already set by user + if(!_manualHostName) { + generateDefaultHostName(mac); + } + // Now try to get our config info from a DHCP server - int ret = _dhcp->beginWithDHCP(mac, timeout, responseTimeout); + int ret = _dhcp->beginWithDHCP(mac, _hostName, timeout, responseTimeout); if (ret == 1) { // We've successfully found a DHCP server and got our configuration // info, so set things accordingly @@ -224,6 +231,32 @@ void EthernetClass::setRetransmissionCount(uint8_t num) SPI.endTransaction(); } +void EthernetClass::generateDefaultHostName(uint8_t *mac) { + // Copy the default host name base + strcpy(_hostName, DEFAULT_HOST_NAME); + + // Append the last 3 bytes of the MAC (HEX'd) + char macAddrStr[3]; + sprintf(macAddrStr, "%02X", mac[3]); + strcat(_hostName, macAddrStr); + sprintf(macAddrStr, "%02X", mac[4]); + strcat(_hostName, macAddrStr); + sprintf(macAddrStr, "%02X", mac[5]); + strcat(_hostName, macAddrStr); +} + +void EthernetClass::setHostName(const char *dhcpHost) { + // Copy the host name and ensure it is null terminated + strncpy(_hostName, dhcpHost, HOST_NAME_MAX_LEN); + _hostName[HOST_NAME_MAX_LEN - 1] = '\0'; + + // Indicate that a host name has been set manually + _manualHostName = true; +} + +char* EthernetClass::getHostName() { + return _hostName; +} diff --git a/src/Ethernet.h b/src/Ethernet.h index 0045de88..3230a0e9 100644 --- a/src/Ethernet.h +++ b/src/Ethernet.h @@ -53,6 +53,9 @@ #include "Server.h" #include "Udp.h" +#define DEFAULT_HOST_NAME "WIZnet" +#define HOST_NAME_MAX_LEN 20 // Max 30 or change the DHCP local buffer size + enum EthernetLinkStatus { Unknown, LinkON, @@ -75,6 +78,8 @@ class EthernetClass { private: static IPAddress _dnsServerAddress; static DhcpClass* _dhcp; + static char _hostName[HOST_NAME_MAX_LEN]; + static bool _manualHostName; public: // Initialise the Ethernet shield to use the provided MAC address and // gain the rest of the configuration through DHCP. @@ -104,6 +109,8 @@ class EthernetClass { void setDnsServerIP(const IPAddress dns_server) { _dnsServerAddress = dns_server; } void setRetransmissionTimeout(uint16_t milliseconds); void setRetransmissionCount(uint8_t num); + void setHostName(const char *hostName); + char* getHostName(); friend class EthernetClient; friend class EthernetServer; @@ -142,6 +149,7 @@ class EthernetClass { static bool socketSendUDP(uint8_t s); // Initialize the "random" source port number static void socketPortRand(uint16_t n); + static void generateDefaultHostName(uint8_t *mac); }; extern EthernetClass Ethernet; @@ -275,6 +283,7 @@ class DhcpClass { uint32_t _dhcpInitialTransactionId; uint32_t _dhcpTransactionId; uint8_t _dhcpMacAddr[6]; + const char* _dhcpHostName; #ifdef __arm__ uint8_t _dhcpLocalIp[4] __attribute__((aligned(4))); uint8_t _dhcpSubnetMask[4] __attribute__((aligned(4))); @@ -312,7 +321,7 @@ class DhcpClass { IPAddress getDhcpServerIp(); IPAddress getDnsServerIp(); - int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + int beginWithDHCP(uint8_t *, const char *hostName, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); int checkLease(); }; From 9773b5bc491932e5369bf62b5246d5d50fd8d920 Mon Sep 17 00:00:00 2001 From: HeAtNet Date: Sun, 28 May 2023 11:55:50 +0200 Subject: [PATCH 2/4] Revert version change --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 0c5d9a9a..f3f36166 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Ethernet -version=2.0.3 +version=2.0.2 author=Various (see AUTHORS file for details) maintainer=Arduino sentence=Enables network connection (local and Internet) using the Arduino Ethernet Board or Shield. From 1f6d782e7ef71641161a9ee8ad8f3f8c6ea47b8d Mon Sep 17 00:00:00 2001 From: HeAtNet Date: Sun, 28 May 2023 12:01:47 +0200 Subject: [PATCH 3/4] Refactor generateDefaultHostName --- src/Ethernet.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/Ethernet.cpp b/src/Ethernet.cpp index 9578f604..1f4d02d8 100644 --- a/src/Ethernet.cpp +++ b/src/Ethernet.cpp @@ -232,17 +232,8 @@ void EthernetClass::setRetransmissionCount(uint8_t num) } void EthernetClass::generateDefaultHostName(uint8_t *mac) { - // Copy the default host name base - strcpy(_hostName, DEFAULT_HOST_NAME); - - // Append the last 3 bytes of the MAC (HEX'd) - char macAddrStr[3]; - sprintf(macAddrStr, "%02X", mac[3]); - strcat(_hostName, macAddrStr); - sprintf(macAddrStr, "%02X", mac[4]); - strcat(_hostName, macAddrStr); - sprintf(macAddrStr, "%02X", mac[5]); - strcat(_hostName, macAddrStr); + // Generate a default host name based on the MAC address + sprintf_P(_hostName, PSTR("%s%02X%02X%02X"), DEFAULT_HOST_NAME, mac[3], mac[4], mac[5]); } void EthernetClass::setHostName(const char *dhcpHost) { From eb14bb73589d3a09033b23a1d760ef38b1d4f4a4 Mon Sep 17 00:00:00 2001 From: HeAtNet Date: Sun, 28 May 2023 15:26:13 +0200 Subject: [PATCH 4/4] Remove sprintf from generateDefaultHostName --- src/Ethernet.cpp | 11 ++++++++++- src/Ethernet.h | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Ethernet.cpp b/src/Ethernet.cpp index 1f4d02d8..4c6dd5c9 100644 --- a/src/Ethernet.cpp +++ b/src/Ethernet.cpp @@ -233,7 +233,16 @@ void EthernetClass::setRetransmissionCount(uint8_t num) void EthernetClass::generateDefaultHostName(uint8_t *mac) { // Generate a default host name based on the MAC address - sprintf_P(_hostName, PSTR("%s%02X%02X%02X"), DEFAULT_HOST_NAME, mac[3], mac[4], mac[5]); + strcpy_P(_hostName, PSTR(DEFAULT_HOST_NAME)); + + // Append last 3 bytes of MAC address to the name + PGM_P hexChars = PSTR("0123456789ABCDEF"); + for (int i = 0; i <= 2; i++) + { + _hostName[DEFAULT_HOST_NAME_LENGTH + i * 2] = pgm_read_byte_near(hexChars + (mac[3 + i] >> 4)); + _hostName[DEFAULT_HOST_NAME_LENGTH + i * 2 + 1] = pgm_read_byte_near(hexChars + (mac[3 + i] & 0x0F)); + } + _hostName[DEFAULT_HOST_NAME_LENGTH + 6] = '\0'; } void EthernetClass::setHostName(const char *dhcpHost) { diff --git a/src/Ethernet.h b/src/Ethernet.h index 3230a0e9..1a29853a 100644 --- a/src/Ethernet.h +++ b/src/Ethernet.h @@ -54,6 +54,7 @@ #include "Udp.h" #define DEFAULT_HOST_NAME "WIZnet" +#define DEFAULT_HOST_NAME_LENGTH (sizeof(DEFAULT_HOST_NAME) - 1) #define HOST_NAME_MAX_LEN 20 // Max 30 or change the DHCP local buffer size enum EthernetLinkStatus {