UIPEthernet / UIPEthernet

UIPEthernet library for Arduino IDE,Eclipse with arduino plugin and MBED/SMeshStudio (AVR,STM32F,ESP8266,Intel ARC32, Nordic nRF51, Teensy boards,Realtek Ameba(RTL8195A,RTL8710)), ENC28j60 network chip. Compatible with Wiznet W5100 Ethernet library API.
304 stars 105 forks source link

Specify hostname (HOST_NAME) #20

Closed csBlueChip closed 6 years ago

csBlueChip commented 7 years ago

The hostname is currently hard-coded in Dhcp.cpp to be "ENC28Jxxyyzz" where xx, yy, zz are the last three octets of the MAC address (in hex ("%02X")) and "ENC28J" is specified by the macro HOST_NAME in Dhcp.h

This means I cannot specify my own hostname without editing the library.

Could you please add a function, such as Ethernet.setHostname("hostname"[, length]) which can be called before Ethernet.begin(...) so I can specify my own hostnames without having multiple copies of the library.

The inclusion of the ", length" parameter allows for non-ascii names where strlen() might fail us.

This example patch affects such a change without breaking backward compatibility...

// new variable
uint8_t* hostname = NULL;
uint8     hostlen = 0;

//new function withing "Ethernet"
// I appreciate that there are both risks and rewards for doing it this way
// copy pointer : cheap and easy -vs- what if the original string is destroyed
// strdup() : never lose the original string -vs- costs & risks of using malloc()
// char hostname[255+1] : never lose the original string -vs- wasted memory
void setHostname(void* vp, int len = -1) 
{
  if (!vp)  return ;
  hostname = (uint8_t*)vp; // copy pointer
  hostlen = (len == -1) ? strlen((char*)vp) : len ;
  if (hostlen > 255)  hostlen = 255 ;
}

void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed)
---
---code
---
if (hostname == NULL) {
-v-existing code
    buffer[17] = strlen(HOST_NAME) + 6; // length of hostname + last 3 bytes of mac address
    strcpy((char*)&(buffer[18]), HOST_NAME);

    printByte((char*)&(buffer[24]), _dhcpMacAddr[3]);
    printByte((char*)&(buffer[26]), _dhcpMacAddr[4]);
    printByte((char*)&(buffer[28]), _dhcpMacAddr[5]);

    //put data in W5100 transmit buffer
    _dhcpUdpSocket.write(buffer, 30);
-^-
} else {
    buffer[17] = hostlen;
    _dhcpUdpSocket.write(buffer, 1+17);
    _dhcpUdpSocket.write(hostname, hostlen);
}
dimitar-kunchev commented 6 years ago

It is actually a little more complicated, but I have tried to do just that - https://github.com/dimitar-kunchev/UIPEthernet/commit/4e6dcb32342c58826ebe9ae2a9bb8f9e185b7c9c So far initial tests show it's working OK...

csBlueChip commented 6 years ago

The problem with using strlen(_hostname) is that you will not be able to specify a (perfectly legal) 0x00 octet in the hostname, and generally add complications for other non-ascii names.

dimitar-kunchev commented 6 years ago

@csBlueChip I believe the valid characters for a hostname are a-z0-9 and hyphen. Also it is limited to 63 characters (or was it 30?) and has to start with a letter. So strlen should work OK.

csBlueChip commented 6 years ago

@dimitar-kunchev http://www.freesoft.org/CIE/RFC/1035/18.htm " is treated as binary information, and can be up to 256 characters in length (including the length octet)."

dimitar-kunchev commented 6 years ago

@csBlueChip That I believe is the specification for DNS, not DHCP. They follow different rules, while sharing the term "hostname".

However - at some level DHCP and DNS are close relatives and in both protocols the length is specified in one octet, so you can have 255 characters hostname that may contain anything. But I still think I have seen a list of restrictions for the DHCP request packet, although it was not in the options RFC 2132.

cassy73 commented 6 years ago

Hi!

THX Dimitar, for developing.

See RFC-s: RFC1541 RFC2131

RFC1533 "3.14. Host Name Option

This option specifies the name of the client. The name may or may not be qualified with the local domain name (see section 3.17 for the preferred way to retrieve the domain name). See RFC 1035 for character set restrictions.

The code for this option is 12, and its minimum length is 1. "

https://tools.ietf.org/html/rfc1034#section-3.1

hostname (Not FQDN, without domain) length must 1-63. Valid characters: 'a'-'z' 'A'-'Z' '0'-'9' and '-'

If the hostname is FQDN the maximum length is 255 " To simplify implementations, the total number of octets that represent a domain name (i.e., the sum of all label octets and label lengths) is limited to 255. "

Best Regards!

dimitar-kunchev commented 6 years ago

@cassy73 RFC1123 2.1, which references RFC952 which states:

<hname> ::= <name>*["."<name>] <name> ::= <let>[*[<let-or-digit-or-hyphen>]<let-or-digit>]

I believe this is exactly where it is indicated what characters are allowed in host names. Maybe this has been updated at some point - i don't know. I am just leaving the information in the thread for historical reasons (if anyone is interested in the future) (Sorry I didn't see your reply for half a year and leave the conversation nowhere. Frankly I an not sure if in your last reply you agreed about the limitation or not :))

Loucotolo commented 6 years ago

Hello, I would like to know where to put these variables: // new variable uint8_t * hostname = NULL; uint8 hostlen = 0;

and if what csBlueChip published this functional

csBlueChip commented 6 years ago

@Loucotolo I chose to do it in dhcp.h ... see here: https://github.com/csBlueChip/UIPEthernet/commit/13d36e14ddaad34fad0f412ad8b1f8baf15c6f12

You will notice I added some extra features (hostname validation and such) so the length is actually initialised to -1 now ...this is all documented in the updated readme.

Of course, feel free to just grab my fork, but I seem to be 6 commits behind, so you might want to check what has been updated here before you use my fork! ...On the bright side [at 6 commits behind] Github tells me there are no merge conflicts :)

BC

Loucotolo commented 6 years ago

@csBlueChip

Hello, I can not use sethostmane. I have the following code:

//https://github.com/skaarj1989/ArduinoWebSockets -> WEBSOKESTS //http://github.com/csBlueChip/UIPEthernet ->

include

include

include

byte mac [] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; WebSocketServer server (81);

void onOpen (WebSocket & ws) { Serial.println (F ("Connected"));

char message [] = "Hello Arduino server!"; ws.send (TEXT, message, strlen (message)); }

void onClose (WebSocket & ws, const code eWebSocketCloseEvent, const char * reason, uint16_t length) { Serial.println (F ("Disconnected")); }

void onMessage (WebSocket & ws, const eWebSocketDataType dataType, const char * message, uint16_t length) { switch (dataType) { case TEXT: Serial.print (F ("Received:")); Serial.println (message); break; case BINARY: Serial.println (F ("Binary data received")); break; } }

void onError (const eWebSocketError) { Serial.print ("Error:"); Serial.println (code); }

void setup () { Serial.begin (115200); while (! Serial);

Serial.println (F ("Initializing ..."));

char hostname [5] = "HELLO"; int len ​​= 5; int err;

if ((err = Ethernet.setHostname (hostname, len))! = 0) { if (err == 1) Serial.println ("invalid_name_pointer ()"); else if (err == 2) Serial.println ("invalid_length ()"); else if (err <0) Serial.println ("invalid_character_position_name (-err)"); else Serial.println ("unknown_error ()"); }

if (Ethernet.begin (mac) == 0) { Serial.println (F ("Can not open ethernet device")); while (true); }

Serial.print (F ("Server IP:")); Serial.println (Ethernet.localIP ());

// ---

server.setOnOpenCallback (onOpen); server.setOnCloseCallback (onClose); server.setOnMessageCallback (onMessage);

server.begin ();

}

void loop () { server.listen (); }

and when I try to call a hello: 81 from me error, and if I connect to ip it works.

capturar

capturar2

csBlueChip commented 6 years ago

It's been a long time, but your code looks good... You can look in your router's DHCP allocation page, and make sure you can see the Arduino with your chosen hostname ("HELLO") ...If you see a default name name ("ENC28J60" or similar) then something has gone wrong in the Arduino code/library. ...If you see the name "HELLO", then the problem is NOT inside your Arduino code ...instead you will need to look at your network routing rules :/ You might end up visiting your "hosts" file!?

On Tue, Aug 21, 2018 at 12:25 PM, Loucotolo notifications@github.com wrote:

@csBlueChip https://github.com/csBlueChip

Hello, I can not use sethostmane. I have the following code:

//https://github.com/skaarj1989/ArduinoWebSockets -> WEBSOKESTS //http://github.com/csBlueChip/UIPEthernet https://github.com/csBlueChip/UIPEthernet ->

include

include

include

byte mac [] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; WebSocketServer server (81);

void onOpen (WebSocket & ws) { Serial.println (F ("Connected"));

char message [] = "Hello Arduino server!"; ws.send (TEXT, message, strlen (message)); }

void onClose (WebSocket & ws, const code eWebSocketCloseEvent, const char

  • reason, uint16_t length) { Serial.println (F ("Disconnected")); }

void onMessage (WebSocket & ws, const eWebSocketDataType dataType, const char * message, uint16_t length) { switch (dataType) { case TEXT: Serial.print (F ("Received:")); Serial.println (message); break; case BINARY: Serial.println (F ("Binary data received")); break; } }

void onError (const eWebSocketError) { Serial.print ("Error:"); Serial.println (code); }

void setup () { Serial.begin (115200); while (! Serial);

Serial.println (F ("Initializing ..."));

char hostname [5] = "HELLO"; int len ​​= 5; int err;

if ((err = Ethernet.setHostname (hostname, len))! = 0) { if (err == 1) Serial.println ("invalid_name_pointer ()"); else if (err == 2) Serial.println ("invalid_length ()"); else if (err <0) Serial.println ("invalid_character_position_name (-err)"); else Serial.println ("unknown_error ()"); }

if (Ethernet.begin (mac) == 0) { Serial.println (F ("Can not open ethernet device")); while (true); }

Serial.print (F ("Server IP:")); Serial.println (Ethernet.localIP ());

// ---

server.setOnOpenCallback (onOpen); server.setOnCloseCallback (onClose); server.setOnMessageCallback (onMessage);

server.begin ();

}

void loop () { server.listen (); }

and when I try to call a hello: 81 from me error, and if I connect to ip it works.

[image: capturar] https://user-images.githubusercontent.com/41787174/44398817-34124200-a53d-11e8-8e40-69bc62ed9b50.PNG

[image: capturar2] https://user-images.githubusercontent.com/41787174/44398820-36749c00-a53d-11e8-9dcd-0ded97be821a.PNG

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/UIPEthernet/UIPEthernet/issues/20#issuecomment-414641615, or mute the thread https://github.com/notifications/unsubscribe-auth/AClAGRQxAGuzPQJV06ps_BaTm9Ts6mzkks5uS-4lgaJpZM4Oh_i6 .

Loucotolo commented 6 years ago

@csBlueChip not as anything hostname "HELO" or ENC28J60 or something similar on the hosts of my router. we can say that hostname function does not work.