diff --git a/smb/kio_smb_browse.cpp b/smb/kio_smb_browse.cpp --- a/smb/kio_smb_browse.cpp +++ b/smb/kio_smb_browse.cpp @@ -219,6 +219,36 @@ kurl.setScheme("smb"); } + // For WS-Discovered hosts we assume they'll respond to DNSSD names on .local but + // they may only respond to llmnr/netbios names. Transparently fall back. + // + // Desktop linuxes tend to have llmnr disabled, by contrast win10 has dnssd enabled, + // so chances are we'll be able to find a host.local more reliably. + // Attempt to resolve foo.local natively, if that works use it, otherwise default to + // the presumed LLMNR/netbios name found during discovery. + // This should then yield reasonable results with any combination of WSD/DNSSD/LLMNR support. + // - WSD+Avahi (on linux) + // - WSD+Win10 (i.e. dnssd + llmnr) + // - WSD+CrappyNAS (e.g. llmnr or netbios only) + // + // NB: smbc has no way to resolve a name without also triggering auth etc.: we must + // rely on the system's ability to resolve DNSSD for this check. + const QLatin1String wsdSuffix(".kio-discovery-wsd"); + if (m_current_url.host().endsWith(wsdSuffix)) { + QString host = m_current_url.host(); + host.chop(wsdSuffix.size()); + const QString dnssd(host + ".local"); + auto dnssdHost = QHostInfo::fromName(dnssd); + if (dnssdHost.error() == QHostInfo::NoError) { + qCDebug(KIO_SMB_LOG) << "Resolved DNSSD name:" << dnssd; + host = dnssd; + } else { + qCDebug(KIO_SMB_LOG) << "Failed to resolve DNSSD name:" << dnssd; + qCDebug(KIO_SMB_LOG) << "Falling back to LLMNR name:" << host; + } + kurl.setHost(host); + } + QString surl = kurl.url(); // transform any links in the form smb:/ into smb:// if (surl.startsWith(QLatin1String("smb:/"))) { diff --git a/smb/wsdiscoverer.cpp b/smb/wsdiscoverer.cpp --- a/smb/wsdiscoverer.cpp +++ b/smb/wsdiscoverer.cpp @@ -164,13 +164,20 @@ } } + // Default the host to the IP unless we have a prettyName in which case we use + // the presumed DNSSD name prettyName.local. listDir will redirect this to the + // LLMNR variant (without .local) should it turn out not resolvable. + QString host = m_endpointUrl.host(); if (computer.isEmpty()) { computer = xi18nc("host entry when no pretty name is available. %1 likely is an IP address", "Unknown Device @ %1", - m_endpointUrl.host()); + host); + } else { + // If we got a DNSSD name, use that, otherwise redirect to on-demand resolution. + host = computer.endsWith(".local") ? computer : computer + ".kio-discovery-wsd"; } - m_discovery.reset(new WSDiscovery(computer, m_endpointUrl.host())); + m_discovery.reset(new WSDiscovery(computer, host)); emit resolved(m_discovery); }