|
37 | 37 | extern "C" {
|
38 | 38 | #include "lwip/err.h"
|
39 | 39 | #include "lwip/dns.h"
|
| 40 | +#include "lwip/dhcp.h" |
40 | 41 | #include "lwip/init.h" // LWIP_VERSION_
|
41 | 42 | #if LWIP_IPV6
|
42 | 43 | #include "lwip/netif.h" // struct netif
|
@@ -466,39 +467,92 @@ IPAddress ESP8266WiFiSTAClass::dnsIP(uint8_t dns_no) {
|
466 | 467 | * Get ESP8266 station DHCP hostname
|
467 | 468 | * @return hostname
|
468 | 469 | */
|
469 |
| -String ESP8266WiFiSTAClass::hostname(void) { |
470 |
| - return String(wifi_station_get_hostname()); |
| 470 | +const char* ESP8266WiFiSTAClass::hostname(void) { |
| 471 | + return wifi_station_get_hostname(); |
471 | 472 | }
|
472 | 473 |
|
473 |
| - |
474 | 474 | /**
|
475 | 475 | * Set ESP8266 station DHCP hostname
|
476 |
| - * @param aHostname max length:32 |
| 476 | + * @param aHostname max length:24 |
477 | 477 | * @return ok
|
478 | 478 | */
|
479 |
| -bool ESP8266WiFiSTAClass::hostname(char* aHostname) { |
480 |
| - if(strlen(aHostname) > 32) { |
| 479 | +bool ESP8266WiFiSTAClass::hostname(String aHostname) { |
| 480 | + /* |
| 481 | + vvvv RFC952 vvvv |
| 482 | + 1. A "name" (Net, Host, Gateway, or Domain name) is a text string up |
| 483 | + to 24 characters drawn from the alphabet (A-Z), digits (0-9), minus |
| 484 | + sign (-), and period (.). Note that periods are only allowed when |
| 485 | + they serve to delimit components of "domain style names". (See |
| 486 | + RFC-921, "Domain Name System Implementation Schedule", for |
| 487 | + background). No blank or space characters are permitted as part of a |
| 488 | + name. No distinction is made between upper and lower case. The first |
| 489 | + character must be an alpha character. The last character must not be |
| 490 | + a minus sign or period. A host which serves as a GATEWAY should have |
| 491 | + "-GATEWAY" or "-GW" as part of its name. Hosts which do not serve as |
| 492 | + Internet gateways should not use "-GATEWAY" and "-GW" as part of |
| 493 | + their names. A host which is a TAC should have "-TAC" as the last |
| 494 | + part of its host name, if it is a DoD host. Single character names |
| 495 | + or nicknames are not allowed. |
| 496 | + ^^^^ RFC952 ^^^^ |
| 497 | +
|
| 498 | + - 24 chars max |
| 499 | + - only a..z A..Z 0..9 -] |
| 500 | + - no '-' as last char |
| 501 | + */ |
| 502 | + |
| 503 | + if (aHostname.length() == 0) { |
| 504 | + DEBUGV("WiFi.(set)hostname(): empty name\n"); |
481 | 505 | return false;
|
482 | 506 | }
|
483 |
| - return wifi_station_set_hostname(aHostname); |
484 |
| -} |
485 | 507 |
|
486 |
| -/** |
487 |
| - * Set ESP8266 station DHCP hostname |
488 |
| - * @param aHostname max length:32 |
489 |
| - * @return ok |
490 |
| - */ |
491 |
| -bool ESP8266WiFiSTAClass::hostname(const char* aHostname) { |
492 |
| - return hostname((char*) aHostname); |
493 |
| -} |
| 508 | + // rework hostname to be RFC compliant |
494 | 509 |
|
495 |
| -/** |
496 |
| - * Set ESP8266 station DHCP hostname |
497 |
| - * @param aHostname max length:32 |
498 |
| - * @return ok |
499 |
| - */ |
500 |
| -bool ESP8266WiFiSTAClass::hostname(const String& aHostname) { |
501 |
| - return hostname((char*) aHostname.c_str()); |
| 510 | + if (aHostname.length() > 24) { |
| 511 | + // nonos-sdk allows 32, but |
| 512 | + // dhcp server may require RFC compliance |
| 513 | + aHostname.remove(24); |
| 514 | + } |
| 515 | + for (size_t i = 0; i < aHostname.length(); i++) |
| 516 | + // replace unallowed chars by dashes |
| 517 | + if (!isalnum(aHostname[i]) && aHostname[i] != '-') |
| 518 | + aHostname[i] = '-'; |
| 519 | + if (aHostname[aHostname.length() - 1] == '-') { |
| 520 | + // check for ending dash |
| 521 | + aHostname[aHostname.length() - 1] = 'x'; |
| 522 | + } |
| 523 | + |
| 524 | + bool ret = wifi_station_set_hostname(aHostname.c_str()); |
| 525 | + |
| 526 | + if (!ret) { |
| 527 | +#ifdef DEBUG_ESP_CORE |
| 528 | + static const char fmt[] PROGMEM = "WiFi.hostname(%s): wifi_station_set_hostname() failed\n"; |
| 529 | + DEBUGV(fmt, aHostname.c_str()); |
| 530 | +#endif |
| 531 | + return false; |
| 532 | + } |
| 533 | + |
| 534 | + // now we should inform dhcp server for this change, using lwip_renew() |
| 535 | + // looping through all existing interface |
| 536 | + // harmless for AP, also compatible with ethernet adapters (to come) |
| 537 | + for (netif* intf = netif_list; intf; intf = intf->next) { |
| 538 | + |
| 539 | + // unconditionally update all known interfaces |
| 540 | + intf->hostname = wifi_station_get_hostname(); |
| 541 | + |
| 542 | + if (netif_dhcp_data(intf) != nullptr) { |
| 543 | + // renew already started DHCP leases |
| 544 | + err_t lwipret = dhcp_renew(intf); |
| 545 | + if (lwipret != ERR_OK) { |
| 546 | +#ifdef DEBUG_ESP_CORE |
| 547 | + static const char fmt[] PROGMEM = "WiFi.hostname(%s): lwIP error %d on interface %c%c (index %d)\n"; |
| 548 | + DEBUGV(fmt, intf->hostname, (int)lwipret, intf->name[0], intf->name[1], intf->num); |
| 549 | +#endif |
| 550 | + ret = false; |
| 551 | + } |
| 552 | + } |
| 553 | + } |
| 554 | + |
| 555 | + return ret; |
502 | 556 | }
|
503 | 557 |
|
504 | 558 | /**
|
|
0 commit comments