1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-07 06:01:35 +03:00

mDNS: restriction to a single interface (#6224)

Default interface is STA (or AP if available and STA is unavailable).
An interface can also be specified in ::begin() by its IP address.
MDNS will not cross interfaces (there is currently no notion of "bridged interfaces")

Multiple instances should be working, this is not tested in this commit.
This commit is contained in:
david gauchard
2019-06-27 09:30:12 +02:00
committed by GitHub
parent 5306976db1
commit f9009b8a5e
6 changed files with 85 additions and 104 deletions

View File

@ -127,6 +127,7 @@ struct netifWrapper
const char* ifhostname () const { return _netif->hostname?: emptyString.c_str(); } const char* ifhostname () const { return _netif->hostname?: emptyString.c_str(); }
const char* ifmac () const { return (const char*)_netif->hwaddr; } const char* ifmac () const { return (const char*)_netif->hwaddr; }
int ifnumber () const { return _netif->num; } int ifnumber () const { return _netif->num; }
bool ifUp () const { return !!(_netif->flags & NETIF_FLAG_UP); }
const ip_addr_t* ipFromNetifNum () const const ip_addr_t* ipFromNetifNum () const
{ {

View File

@ -87,13 +87,16 @@ MDNSResponder::~MDNSResponder(void) {
* Finally the responder is (re)started * Finally the responder is (re)started
* *
*/ */
bool MDNSResponder::begin(const char* p_pcHostname) { bool MDNSResponder::begin(const char* p_pcHostname, const IPAddress& p_IPAddress, uint32_t p_u32TTL) {
(void)p_u32TTL; // ignored
bool bResult = false; bool bResult = false;
if (0 == m_pUDPContext) { if (0 == m_pUDPContext) {
if (_setHostname(p_pcHostname)) { if (_setHostname(p_pcHostname)) {
m_IPAddress = p_IPAddress;
m_GotIPHandler = WiFi.onStationModeGotIP([this](const WiFiEventStationModeGotIP& pEvent) { m_GotIPHandler = WiFi.onStationModeGotIP([this](const WiFiEventStationModeGotIP& pEvent) {
(void) pEvent; (void) pEvent;
// Ensure that _restart() runs in USER context // Ensure that _restart() runs in USER context
@ -116,18 +119,6 @@ bool MDNSResponder::begin(const char* p_pcHostname) {
return bResult; return bResult;
} }
/*
* MDNSResponder::begin (LEGACY)
*/
bool MDNSResponder::begin(const char* p_pcHostname,
IPAddress p_IPAddress,
uint32_t p_u32TTL /*= 120*/) {
(void) p_IPAddress;
(void) p_u32TTL;
return begin(p_pcHostname);
}
/* /*
* MDNSResponder::close * MDNSResponder::close
* *

View File

@ -175,17 +175,10 @@ public:
// Start the MDNS responder by setting the default hostname // Start the MDNS responder by setting the default hostname
// Later call MDNS::update() in every 'loop' to run the process loop // Later call MDNS::update() in every 'loop' to run the process loop
// (probing, announcing, responding, ...) // (probing, announcing, responding, ...)
bool begin(const char* p_pcHostname); // if interfaceAddress is not specified, default interface is STA, or AP when STA is not set
bool begin(const String& p_strHostname) {return begin(p_strHostname.c_str());} bool begin(const char* p_pcHostname, const IPAddress& p_IPAddress = INADDR_ANY, uint32_t p_u32TTL = 120 /*ignored*/);
// for compatibility bool begin(const String& p_strHostname, const IPAddress& p_IPAddress = INADDR_ANY, uint32_t p_u32TTL = 120 /*ignored*/) {return begin(p_strHostname.c_str(), p_IPAddress, p_u32TTL);}
bool begin(const char* p_pcHostname,
IPAddress p_IPAddress, // ignored
uint32_t p_u32TTL = 120); // ignored
bool begin(const String& p_strHostname,
IPAddress p_IPAddress, // ignored
uint32_t p_u32TTL = 120) { // ignored
return begin(p_strHostname.c_str(), p_IPAddress, p_u32TTL);
}
// Finish MDNS processing // Finish MDNS processing
bool close(void); bool close(void);
// for esp32 compatability // for esp32 compatability
@ -487,12 +480,12 @@ public:
const char* p_pcDivider = "-", const char* p_pcDivider = "-",
const char* p_pcDefaultDomain = 0); const char* p_pcDefaultDomain = 0);
protected:
/** STRUCTS **/ /** STRUCTS **/
public:
/** /**
* MDNSServiceInfo, used in application callbacks * MDNSServiceInfo, used in application callbacks
*/ */
public:
struct MDNSServiceInfo struct MDNSServiceInfo
{ {
MDNSServiceInfo(MDNSResponder& p_pM,MDNSResponder::hMDNSServiceQuery p_hS,uint32_t p_u32A) MDNSServiceInfo(MDNSResponder& p_pM,MDNSResponder::hMDNSServiceQuery p_hS,uint32_t p_u32A)
@ -1155,6 +1148,7 @@ protected:
MDNSDynamicServiceTxtCallbackFunc m_fnServiceTxtCallback; MDNSDynamicServiceTxtCallbackFunc m_fnServiceTxtCallback;
bool m_bPassivModeEnabled; bool m_bPassivModeEnabled;
stcProbeInformation m_HostProbeInformation; stcProbeInformation m_HostProbeInformation;
IPAddress m_IPAddress;
/** CONTROL **/ /** CONTROL **/
/* MAINTENANCE */ /* MAINTENANCE */
@ -1201,8 +1195,7 @@ protected:
/** TRANSFER **/ /** TRANSFER **/
/* SENDING */ /* SENDING */
bool _sendMDNSMessage(stcMDNSSendParameter& p_SendParameter); bool _sendMDNSMessage(stcMDNSSendParameter& p_SendParameter);
bool _sendMDNSMessage_Multicast(MDNSResponder::stcMDNSSendParameter& p_rSendParameter, bool _sendMDNSMessage_Multicast(MDNSResponder::stcMDNSSendParameter& p_rSendParameter);
int p_iWiFiOpMode);
bool _prepareMDNSMessage(stcMDNSSendParameter& p_SendParameter, bool _prepareMDNSMessage(stcMDNSSendParameter& p_SendParameter,
IPAddress p_IPAddress); IPAddress p_IPAddress);
bool _sendMDNSServiceQuery(const stcMDNSServiceQuery& p_ServiceQuery); bool _sendMDNSServiceQuery(const stcMDNSServiceQuery& p_ServiceQuery);
@ -1210,7 +1203,7 @@ protected:
uint16_t p_u16QueryType, uint16_t p_u16QueryType,
stcMDNSServiceQuery::stcAnswer* p_pKnownAnswers = 0); stcMDNSServiceQuery::stcAnswer* p_pKnownAnswers = 0);
IPAddress _getResponseMulticastInterface(int p_iWiFiOpModes) const; const IPAddress& _getResponseMulticastInterface() const { return m_IPAddress; }
uint8_t _replyMaskForHost(const stcMDNS_RRHeader& p_RRHeader, uint8_t _replyMaskForHost(const stcMDNS_RRHeader& p_RRHeader,
bool* p_pbFullNameMatch = 0) const; bool* p_pbFullNameMatch = 0) const;

View File

@ -91,6 +91,51 @@ bool MDNSResponder::_process(bool p_bUserContext) {
*/ */
bool MDNSResponder::_restart(void) { bool MDNSResponder::_restart(void) {
// check m_IPAddress
if (!m_IPAddress.isSet()) {
IPAddress sta = WiFi.localIP();
IPAddress ap = WiFi.softAPIP();
if (!sta.isSet() && !ap.isSet()) {
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] internal interfaces (STA, AP) are not set (none was specified)\n")));
return false;
}
if (sta.isSet()) {
if (ap.isSet())
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] default interface STA selected over AP (none was specified)\n")));
else
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] default interface STA selected\n")));
m_IPAddress = sta;
} else {
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] default interface AP selected (none was specified)\n")));
m_IPAddress = ap;
}
// continue to ensure interface is UP
}
// check existence of this IP address in the interface list
bool found = false;
for (auto a: addrList)
if (m_IPAddress == a.addr()) {
if (a.ifUp()) {
found = true;
break;
}
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] found interface for IP '%s' but it is not UP\n"), m_IPAddress.toString().c_str()););
}
if (!found) {
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] interface defined by IP '%s' not found\n"), m_IPAddress.toString().c_str()););
return false;
}
return ((_resetProbeStatus(true)) && // Stop and restart probing return ((_resetProbeStatus(true)) && // Stop and restart probing
(_allocUDPContext())); // Restart UDP (_allocUDPContext())); // Restart UDP
} }
@ -314,7 +359,7 @@ bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHea
// IP4 address was asked for // IP4 address was asked for
#ifdef MDNS_IP4_SUPPORT #ifdef MDNS_IP4_SUPPORT
if ((AnswerType_A == pKnownRRAnswer->answerType()) && if ((AnswerType_A == pKnownRRAnswer->answerType()) &&
(((stcMDNS_RRAnswerA*)pKnownRRAnswer)->m_IPAddress == _getResponseMulticastInterface(SOFTAP_MODE | STATION_MODE))) { (((stcMDNS_RRAnswerA*)pKnownRRAnswer)->m_IPAddress == _getResponseMulticastInterface())) {
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: IP4 address already known... skipping!\n"));); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: IP4 address already known... skipping!\n")););
sendParameter.m_u8HostReplyMask &= ~ContentFlag_A; sendParameter.m_u8HostReplyMask &= ~ContentFlag_A;
@ -325,7 +370,7 @@ bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHea
// IP6 address was asked for // IP6 address was asked for
#ifdef MDNS_IP6_SUPPORT #ifdef MDNS_IP6_SUPPORT
if ((AnswerType_AAAA == pAnswerRR->answerType()) && if ((AnswerType_AAAA == pAnswerRR->answerType()) &&
(((stcMDNS_RRAnswerAAAA*)pAnswerRR)->m_IPAddress == _getResponseMulticastInterface(SOFTAP_MODE | STATION_MODE))) { (((stcMDNS_RRAnswerAAAA*)pAnswerRR)->m_IPAddress == _getResponseMulticastInterface())) {
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: IP6 address already known... skipping!\n"));); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: IP6 address already known... skipping!\n")););
sendParameter.m_u8HostReplyMask &= ~ContentFlag_AAAA; sendParameter.m_u8HostReplyMask &= ~ContentFlag_AAAA;
@ -343,7 +388,7 @@ bool MDNSResponder::_parseQuery(const MDNSResponder::stcMDNS_MsgHeader& p_MsgHea
// Host domain match // Host domain match
#ifdef MDNS_IP4_SUPPORT #ifdef MDNS_IP4_SUPPORT
if (AnswerType_A == pKnownRRAnswer->answerType()) { if (AnswerType_A == pKnownRRAnswer->answerType()) {
IPAddress localIPAddress(_getResponseMulticastInterface(SOFTAP_MODE | STATION_MODE)); IPAddress localIPAddress(_getResponseMulticastInterface());
if (((stcMDNS_RRAnswerA*)pKnownRRAnswer)->m_IPAddress == localIPAddress) { if (((stcMDNS_RRAnswerA*)pKnownRRAnswer)->m_IPAddress == localIPAddress) {
// SAME IP address -> We've received an old message from ourselfs (same IP) // SAME IP address -> We've received an old message from ourselfs (same IP)
DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (IP4) WON (was an old message)!\n"));); DEBUG_EX_RX(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _parseQuery: Tiebreak (IP4) WON (was an old message)!\n")););
@ -1039,7 +1084,7 @@ bool MDNSResponder::_updateProbeStatus(void) {
// Probe host domain // Probe host domain
if ((ProbingStatus_ReadyToStart == m_HostProbeInformation.m_ProbingStatus) && // Ready to get started AND if ((ProbingStatus_ReadyToStart == m_HostProbeInformation.m_ProbingStatus) && // Ready to get started AND
//TODO: Fix the following to allow Ethernet shield or other interfaces //TODO: Fix the following to allow Ethernet shield or other interfaces
(_getResponseMulticastInterface(SOFTAP_MODE | STATION_MODE) != IPAddress())) { // Has IP address (_getResponseMulticastInterface() != IPAddress())) { // Has IP address
DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Starting host probing...\n"));); DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _updateProbeStatus: Starting host probing...\n")););
// First probe delay SHOULD be random 0-250 ms // First probe delay SHOULD be random 0-250 ms
@ -1721,7 +1766,7 @@ uint8_t MDNSResponder::_replyMaskForHost(const MDNSResponder::stcMDNS_RRHeader&
// PTR request // PTR request
#ifdef MDNS_IP4_SUPPORT #ifdef MDNS_IP4_SUPPORT
stcMDNS_RRDomain reverseIP4Domain; stcMDNS_RRDomain reverseIP4Domain;
if ((_buildDomainForReverseIP4(_getResponseMulticastInterface(SOFTAP_MODE | STATION_MODE), reverseIP4Domain)) && if ((_buildDomainForReverseIP4(_getResponseMulticastInterface(), reverseIP4Domain)) &&
(p_RRHeader.m_Domain == reverseIP4Domain)) { (p_RRHeader.m_Domain == reverseIP4Domain)) {
// Reverse domain match // Reverse domain match
u8ReplyMask |= ContentFlag_PTR_IP4; u8ReplyMask |= ContentFlag_PTR_IP4;

View File

@ -59,22 +59,22 @@ namespace MDNSImplementation {
#ifdef DEBUG_ESP_MDNS_INFO #ifdef DEBUG_ESP_MDNS_INFO
#define DEBUG_EX_INFO(A) A #define DEBUG_EX_INFO(A) A
#else #else
#define DEBUG_EX_INFO(A) #define DEBUG_EX_INFO(A) do { (void)0; } while (0)
#endif #endif
#ifdef DEBUG_ESP_MDNS_ERR #ifdef DEBUG_ESP_MDNS_ERR
#define DEBUG_EX_ERR(A) A #define DEBUG_EX_ERR(A) A
#else #else
#define DEBUG_EX_ERR(A) #define DEBUG_EX_ERR(A) do { (void)0; } while (0)
#endif #endif
#ifdef DEBUG_ESP_MDNS_TX #ifdef DEBUG_ESP_MDNS_TX
#define DEBUG_EX_TX(A) A #define DEBUG_EX_TX(A) A
#else #else
#define DEBUG_EX_TX(A) #define DEBUG_EX_TX(A) do { (void)0; } while (0)
#endif #endif
#ifdef DEBUG_ESP_MDNS_RX #ifdef DEBUG_ESP_MDNS_RX
#define DEBUG_EX_RX(A) A #define DEBUG_EX_RX(A) A
#else #else
#define DEBUG_EX_RX(A) #define DEBUG_EX_RX(A) do { (void)0; } while (0)
#endif #endif
#ifdef DEBUG_ESP_PORT #ifdef DEBUG_ESP_PORT
@ -83,10 +83,10 @@ namespace MDNSImplementation {
#define DEBUG_OUTPUT Serial #define DEBUG_OUTPUT Serial
#endif #endif
#else #else
#define DEBUG_EX_INFO(A) #define DEBUG_EX_INFO(A) do { (void)0; } while (0)
#define DEBUG_EX_ERR(A) #define DEBUG_EX_ERR(A) do { (void)0; } while (0)
#define DEBUG_EX_TX(A) #define DEBUG_EX_TX(A) do { (void)0; } while (0)
#define DEBUG_EX_RX(A) #define DEBUG_EX_RX(A) do { (void)0; } while (0)
#endif #endif

View File

@ -76,25 +76,16 @@ bool MDNSResponder::_sendMDNSMessage(MDNSResponder::stcMDNSSendParameter& p_rSen
bool bResult = true; bool bResult = true;
if (p_rSendParameter.m_bResponse) { if (p_rSendParameter.m_bResponse &&
if (p_rSendParameter.m_bUnicast) { // Unicast response -> Send to querier p_rSendParameter.m_bUnicast) { // Unicast response -> Send to querier
DEBUG_EX_ERR(if (!m_pUDPContext->getRemoteAddress()) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage: MISSING remote address for response!\n")); }); DEBUG_EX_ERR(if (!m_pUDPContext->getRemoteAddress()) { DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _sendMDNSMessage: MISSING remote address for response!\n")); });
IPAddress ipRemote; IPAddress ipRemote;
ipRemote = m_pUDPContext->getRemoteAddress(); ipRemote = m_pUDPContext->getRemoteAddress();
bResult = ((_prepareMDNSMessage(p_rSendParameter, _getResponseMulticastInterface(SOFTAP_MODE | STATION_MODE))) && bResult = ((_prepareMDNSMessage(p_rSendParameter, _getResponseMulticastInterface())) &&
(m_pUDPContext->send(ipRemote, m_pUDPContext->getRemotePort()))); (m_pUDPContext->send(ipRemote, m_pUDPContext->getRemotePort())));
}
else { // Multicast response -> Send via the same network interface, that received the query
bResult = _sendMDNSMessage_Multicast(p_rSendParameter, (SOFTAP_MODE | STATION_MODE));
}
} }
else { // Multicast query -> Send by all available network interfaces else { // Multicast response
const int caiWiFiOpModes[2] = { SOFTAP_MODE, STATION_MODE }; bResult = _sendMDNSMessage_Multicast(p_rSendParameter);
for (int iInterfaceId=0; ((bResult) && (iInterfaceId<=1)); ++iInterfaceId) {
if (wifi_get_opmode() & caiWiFiOpModes[iInterfaceId]) {
bResult = _sendMDNSMessage_Multicast(p_rSendParameter, caiWiFiOpModes[iInterfaceId]);
}
}
} }
// Finally clear service reply masks // Finally clear service reply masks
@ -112,12 +103,12 @@ bool MDNSResponder::_sendMDNSMessage(MDNSResponder::stcMDNSSendParameter& p_rSen
* Fills the UDP output buffer (via _prepareMDNSMessage) and sends the buffer * Fills the UDP output buffer (via _prepareMDNSMessage) and sends the buffer
* via the selected WiFi interface (Station or AP) * via the selected WiFi interface (Station or AP)
*/ */
bool MDNSResponder::_sendMDNSMessage_Multicast(MDNSResponder::stcMDNSSendParameter& p_rSendParameter, bool MDNSResponder::_sendMDNSMessage_Multicast(MDNSResponder::stcMDNSSendParameter& p_rSendParameter) {
int p_iWiFiOpMode) {
bool bResult = false; bool bResult = false;
IPAddress fromIPAddress; IPAddress fromIPAddress;
fromIPAddress = _getResponseMulticastInterface(p_iWiFiOpMode); fromIPAddress = _getResponseMulticastInterface();
m_pUDPContext->setMulticastInterface(fromIPAddress); m_pUDPContext->setMulticastInterface(fromIPAddress);
#ifdef MDNS_IP4_SUPPORT #ifdef MDNS_IP4_SUPPORT
@ -365,46 +356,6 @@ bool MDNSResponder::_sendMDNSQuery(const MDNSResponder::stcMDNS_RRDomain& p_Quer
return bResult; return bResult;
} }
/*
* MDNSResponder::_getResponseMulticastInterface
*
* Selects the appropriate interface for responses.
* If AP mode is enabled and the remote contact is in the APs local net, then the
* AP interface is used to send the response.
* Otherwise the Station interface (if available) is used.
*
*/
IPAddress MDNSResponder::_getResponseMulticastInterface(int p_iWiFiOpModes) const {
ip_info IPInfo_Local;
bool bFoundMatch = false;
if ((p_iWiFiOpModes & SOFTAP_MODE) &&
(wifi_get_opmode() & SOFTAP_MODE)) {
//DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _getResponseMulticastInterface: SOFTAP_MODE\n")););
// Get remote IP address
IPAddress IP_Remote;
IP_Remote = m_pUDPContext->getRemoteAddress();
// Get local (AP) IP address
wifi_get_ip_info(SOFTAP_IF, &IPInfo_Local);
if ((IPInfo_Local.ip.addr) && // Has local AP IP address AND
(ip4_addr_netcmp(ip_2_ip4((const ip_addr_t*)IP_Remote), &IPInfo_Local.ip, &IPInfo_Local.netmask))) { // Remote address is in the same subnet as the AP
bFoundMatch = true;
}
}
if ((!bFoundMatch) &&
(p_iWiFiOpModes & STATION_MODE) &&
(wifi_get_opmode() & STATION_MODE)) {
//DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _getResponseMulticastInterface: STATION_MODE\n")););
// Get local (STATION) IP address
wifi_get_ip_info(STATION_IF, &IPInfo_Local);
}
//DEBUG_EX_INFO(DEBUG_OUTPUT.printf_P(PSTR("[MDNSResponder] _getResponseMulticastInterface(%i): %s\n"), p_iWiFiOpModes, IPAddress(IPInfo_Local.ip).toString().c_str()););
return IPAddress(IPInfo_Local.ip);
}
/** /**
* HELPERS * HELPERS
*/ */