summaryrefslogtreecommitdiffstats
path: root/netwerk/dns
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/dns')
-rw-r--r--netwerk/dns/ChildDNSService.cpp330
-rw-r--r--netwerk/dns/ChildDNSService.h60
-rw-r--r--netwerk/dns/DNS.cpp368
-rw-r--r--netwerk/dns/DNS.h183
-rw-r--r--netwerk/dns/DNSListenerProxy.cpp43
-rw-r--r--netwerk/dns/DNSListenerProxy.h72
-rw-r--r--netwerk/dns/DNSRequestChild.cpp313
-rw-r--r--netwerk/dns/DNSRequestChild.h61
-rw-r--r--netwerk/dns/DNSRequestParent.cpp132
-rw-r--r--netwerk/dns/DNSRequestParent.h50
-rw-r--r--netwerk/dns/GetAddrInfo.cpp369
-rw-r--r--netwerk/dns/GetAddrInfo.h67
-rw-r--r--netwerk/dns/PDNSParams.h23
-rw-r--r--netwerk/dns/PDNSRequest.ipdl36
-rw-r--r--netwerk/dns/PDNSRequestParams.ipdlh31
-rw-r--r--netwerk/dns/effective_tld_names.dat10834
-rw-r--r--netwerk/dns/mdns/libmdns/MDNSResponderOperator.cpp779
-rw-r--r--netwerk/dns/mdns/libmdns/MDNSResponderOperator.h152
-rw-r--r--netwerk/dns/mdns/libmdns/MDNSResponderReply.cpp302
-rw-r--r--netwerk/dns/mdns/libmdns/MDNSResponderReply.h164
-rw-r--r--netwerk/dns/mdns/libmdns/MulticastDNSAndroid.jsm244
-rw-r--r--netwerk/dns/mdns/libmdns/fallback/DNSPacket.jsm297
-rw-r--r--netwerk/dns/mdns/libmdns/fallback/DNSRecord.jsm70
-rw-r--r--netwerk/dns/mdns/libmdns/fallback/DNSResourceRecord.jsm221
-rw-r--r--netwerk/dns/mdns/libmdns/fallback/DNSTypes.jsm100
-rw-r--r--netwerk/dns/mdns/libmdns/fallback/DataReader.jsm133
-rw-r--r--netwerk/dns/mdns/libmdns/fallback/DataWriter.jsm98
-rw-r--r--netwerk/dns/mdns/libmdns/fallback/MulticastDNS.jsm875
-rw-r--r--netwerk/dns/mdns/libmdns/moz.build56
-rw-r--r--netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.cpp285
-rw-r--r--netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.h48
-rw-r--r--netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.js201
-rw-r--r--netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.manifest3
-rw-r--r--netwerk/dns/mdns/libmdns/nsDNSServiceInfo.cpp209
-rw-r--r--netwerk/dns/mdns/libmdns/nsDNSServiceInfo.h50
-rw-r--r--netwerk/dns/mdns/libmdns/nsMulticastDNSModule.cpp61
-rw-r--r--netwerk/dns/mdns/moz.build13
-rw-r--r--netwerk/dns/mdns/nsIDNSServiceDiscovery.idl219
-rw-r--r--netwerk/dns/moz.build78
-rw-r--r--netwerk/dns/nameprep.c347
-rw-r--r--netwerk/dns/nameprep_template.c139
-rw-r--r--netwerk/dns/nameprepdata.c2588
-rw-r--r--netwerk/dns/nsDNSService2.cpp1071
-rw-r--r--netwerk/dns/nsDNSService2.h72
-rw-r--r--netwerk/dns/nsEffectiveTLDService.cpp368
-rw-r--r--netwerk/dns/nsEffectiveTLDService.h98
-rw-r--r--netwerk/dns/nsHostResolver.cpp1579
-rw-r--r--netwerk/dns/nsHostResolver.h372
-rw-r--r--netwerk/dns/nsIDNKitInterface.h195
-rw-r--r--netwerk/dns/nsIDNSListener.idl46
-rw-r--r--netwerk/dns/nsIDNSRecord.idl100
-rw-r--r--netwerk/dns/nsIDNSService.idl171
-rw-r--r--netwerk/dns/nsIDNService.cpp959
-rw-r--r--netwerk/dns/nsIDNService.h195
-rw-r--r--netwerk/dns/nsIEffectiveTLDService.idl125
-rw-r--r--netwerk/dns/nsIIDNService.idl58
-rw-r--r--netwerk/dns/nsPIDNSService.idl34
-rw-r--r--netwerk/dns/prepare_tlds.py121
-rw-r--r--netwerk/dns/punycode.c289
-rw-r--r--netwerk/dns/punycode.h108
60 files changed, 26665 insertions, 0 deletions
diff --git a/netwerk/dns/ChildDNSService.cpp b/netwerk/dns/ChildDNSService.cpp
new file mode 100644
index 000000000..a3a1f3347
--- /dev/null
+++ b/netwerk/dns/ChildDNSService.cpp
@@ -0,0 +1,330 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/net/ChildDNSService.h"
+#include "nsIDNSListener.h"
+#include "nsIIOService.h"
+#include "nsIThread.h"
+#include "nsThreadUtils.h"
+#include "nsIXPConnect.h"
+#include "nsIPrefService.h"
+#include "nsIProtocolProxyService.h"
+#include "nsNetCID.h"
+#include "mozilla/net/NeckoChild.h"
+#include "mozilla/net/DNSListenerProxy.h"
+#include "nsServiceManagerUtils.h"
+
+namespace mozilla {
+namespace net {
+
+//-----------------------------------------------------------------------------
+// ChildDNSService
+//-----------------------------------------------------------------------------
+
+static ChildDNSService *gChildDNSService;
+static const char kPrefNameDisablePrefetch[] = "network.dns.disablePrefetch";
+
+ChildDNSService* ChildDNSService::GetSingleton()
+{
+ MOZ_ASSERT(IsNeckoChild());
+
+ if (!gChildDNSService) {
+ gChildDNSService = new ChildDNSService();
+ }
+
+ NS_ADDREF(gChildDNSService);
+ return gChildDNSService;
+}
+
+NS_IMPL_ISUPPORTS(ChildDNSService,
+ nsIDNSService,
+ nsPIDNSService,
+ nsIObserver)
+
+ChildDNSService::ChildDNSService()
+ : mFirstTime(true)
+ , mDisablePrefetch(false)
+ , mPendingRequestsLock("DNSPendingRequestsLock")
+{
+ MOZ_ASSERT(IsNeckoChild());
+}
+
+ChildDNSService::~ChildDNSService()
+{
+
+}
+
+void
+ChildDNSService::GetDNSRecordHashKey(const nsACString &aHost,
+ uint32_t aFlags,
+ const nsACString &aNetworkInterface,
+ nsIDNSListener* aListener,
+ nsACString &aHashKey)
+{
+ aHashKey.Assign(aHost);
+ aHashKey.AppendInt(aFlags);
+ if (!aNetworkInterface.IsEmpty()) {
+ aHashKey.Append(aNetworkInterface);
+ }
+ aHashKey.AppendPrintf("%p", aListener);
+}
+
+//-----------------------------------------------------------------------------
+// ChildDNSService::nsIDNSService
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+ChildDNSService::AsyncResolve(const nsACString &hostname,
+ uint32_t flags,
+ nsIDNSListener *listener,
+ nsIEventTarget *target_,
+ nsICancelable **result)
+{
+ return AsyncResolveExtended(hostname, flags, EmptyCString(), listener,
+ target_, result);
+}
+
+NS_IMETHODIMP
+ChildDNSService::AsyncResolveExtended(const nsACString &hostname,
+ uint32_t flags,
+ const nsACString &aNetworkInterface,
+ nsIDNSListener *listener,
+ nsIEventTarget *target_,
+ nsICancelable **result)
+{
+ NS_ENSURE_TRUE(gNeckoChild != nullptr, NS_ERROR_FAILURE);
+
+ if (mDisablePrefetch && (flags & RESOLVE_SPECULATE)) {
+ return NS_ERROR_DNS_LOOKUP_QUEUE_FULL;
+ }
+
+ // We need original flags for the pending requests hash.
+ uint32_t originalFlags = flags;
+
+ // Support apps being 'offline' even if parent is not: avoids DNS traffic by
+ // apps that have been told they are offline.
+ if (GetOffline()) {
+ flags |= RESOLVE_OFFLINE;
+ }
+
+ // We need original listener for the pending requests hash.
+ nsIDNSListener *originalListener = listener;
+
+ // make sure JS callers get notification on the main thread
+ nsCOMPtr<nsIEventTarget> target = target_;
+ nsCOMPtr<nsIXPConnectWrappedJS> wrappedListener = do_QueryInterface(listener);
+ if (wrappedListener && !target) {
+ nsCOMPtr<nsIThread> mainThread;
+ NS_GetMainThread(getter_AddRefs(mainThread));
+ target = do_QueryInterface(mainThread);
+ }
+ if (target) {
+ // Guarantee listener freed on main thread. Not sure we need this in child
+ // (or in parent in nsDNSService.cpp) but doesn't hurt.
+ listener = new DNSListenerProxy(listener, target);
+ }
+
+ RefPtr<DNSRequestChild> childReq =
+ new DNSRequestChild(nsCString(hostname), flags,
+ nsCString(aNetworkInterface),
+ listener, target);
+
+ {
+ MutexAutoLock lock(mPendingRequestsLock);
+ nsCString key;
+ GetDNSRecordHashKey(hostname, originalFlags, aNetworkInterface,
+ originalListener, key);
+ nsTArray<RefPtr<DNSRequestChild>> *hashEntry;
+ if (mPendingRequests.Get(key, &hashEntry)) {
+ hashEntry->AppendElement(childReq);
+ } else {
+ hashEntry = new nsTArray<RefPtr<DNSRequestChild>>();
+ hashEntry->AppendElement(childReq);
+ mPendingRequests.Put(key, hashEntry);
+ }
+ }
+
+ childReq->StartRequest();
+
+ childReq.forget(result);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ChildDNSService::CancelAsyncResolve(const nsACString &aHostname,
+ uint32_t aFlags,
+ nsIDNSListener *aListener,
+ nsresult aReason)
+{
+ return CancelAsyncResolveExtended(aHostname, aFlags, EmptyCString(),
+ aListener, aReason);
+}
+
+NS_IMETHODIMP
+ChildDNSService::CancelAsyncResolveExtended(const nsACString &aHostname,
+ uint32_t aFlags,
+ const nsACString &aNetworkInterface,
+ nsIDNSListener *aListener,
+ nsresult aReason)
+{
+ if (mDisablePrefetch && (aFlags & RESOLVE_SPECULATE)) {
+ return NS_ERROR_DNS_LOOKUP_QUEUE_FULL;
+ }
+
+ MutexAutoLock lock(mPendingRequestsLock);
+ nsTArray<RefPtr<DNSRequestChild>> *hashEntry;
+ nsCString key;
+ GetDNSRecordHashKey(aHostname, aFlags, aNetworkInterface, aListener, key);
+ if (mPendingRequests.Get(key, &hashEntry)) {
+ // We cancel just one.
+ hashEntry->ElementAt(0)->Cancel(aReason);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ChildDNSService::Resolve(const nsACString &hostname,
+ uint32_t flags,
+ nsIDNSRecord **result)
+{
+ // not planning to ever support this, since sync IPDL is evil.
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
+ChildDNSService::GetDNSCacheEntries(nsTArray<mozilla::net::DNSCacheEntries> *args)
+{
+ // Only used by networking dashboard, so may not ever need this in child.
+ // (and would provide a way to spy on what hosts other apps are connecting to,
+ // unless we start keeping per-app DNS caches).
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
+ChildDNSService::GetMyHostName(nsACString &result)
+{
+ // TODO: get value from parent during PNecko construction?
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+void
+ChildDNSService::NotifyRequestDone(DNSRequestChild *aDnsRequest)
+{
+ // We need the original flags and listener for the pending requests hash.
+ uint32_t originalFlags = aDnsRequest->mFlags & ~RESOLVE_OFFLINE;
+ nsCOMPtr<nsIDNSListener> originalListener = aDnsRequest->mListener;
+ nsCOMPtr<nsIDNSListenerProxy> wrapper = do_QueryInterface(originalListener);
+ if (wrapper) {
+ wrapper->GetOriginalListener(getter_AddRefs(originalListener));
+ if (NS_WARN_IF(!originalListener)) {
+ MOZ_ASSERT(originalListener);
+ return;
+ }
+ }
+
+ MutexAutoLock lock(mPendingRequestsLock);
+
+ nsCString key;
+ GetDNSRecordHashKey(aDnsRequest->mHost, originalFlags,
+ aDnsRequest->mNetworkInterface, originalListener, key);
+
+ nsTArray<RefPtr<DNSRequestChild>> *hashEntry;
+
+ if (mPendingRequests.Get(key, &hashEntry)) {
+ int idx;
+ if ((idx = hashEntry->IndexOf(aDnsRequest))) {
+ hashEntry->RemoveElementAt(idx);
+ if (hashEntry->IsEmpty()) {
+ mPendingRequests.Remove(key);
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// ChildDNSService::nsPIDNSService
+//-----------------------------------------------------------------------------
+
+nsresult
+ChildDNSService::Init()
+{
+ // Disable prefetching either by explicit preference or if a manual proxy
+ // is configured
+ bool disablePrefetch = false;
+ int proxyType = nsIProtocolProxyService::PROXYCONFIG_DIRECT;
+
+ nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
+ if (prefs) {
+ prefs->GetIntPref("network.proxy.type", &proxyType);
+ prefs->GetBoolPref(kPrefNameDisablePrefetch, &disablePrefetch);
+ }
+
+ if (mFirstTime) {
+ mFirstTime = false;
+ if (prefs) {
+ prefs->AddObserver(kPrefNameDisablePrefetch, this, false);
+
+ // Monitor these to see if there is a change in proxy configuration
+ // If a manual proxy is in use, disable prefetch implicitly
+ prefs->AddObserver("network.proxy.type", this, false);
+ }
+ }
+
+ mDisablePrefetch = disablePrefetch ||
+ (proxyType == nsIProtocolProxyService::PROXYCONFIG_MANUAL);
+
+ return NS_OK;
+}
+
+nsresult
+ChildDNSService::Shutdown()
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ChildDNSService::GetPrefetchEnabled(bool *outVal)
+{
+ *outVal = !mDisablePrefetch;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ChildDNSService::SetPrefetchEnabled(bool inVal)
+{
+ mDisablePrefetch = !inVal;
+ return NS_OK;
+}
+
+bool
+ChildDNSService::GetOffline() const
+{
+ bool offline = false;
+ nsCOMPtr<nsIIOService> io = do_GetService(NS_IOSERVICE_CONTRACTID);
+ if (io) {
+ io->GetOffline(&offline);
+ }
+ return offline;
+}
+
+//-----------------------------------------------------------------------------
+// ChildDNSService::nsIObserver
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+ChildDNSService::Observe(nsISupports *subject, const char *topic,
+ const char16_t *data)
+{
+ // we are only getting called if a preference has changed.
+ NS_ASSERTION(strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0,
+ "unexpected observe call");
+
+ // Reread prefs
+ Init();
+ return NS_OK;
+}
+
+} // namespace net
+} // namespace mozilla
diff --git a/netwerk/dns/ChildDNSService.h b/netwerk/dns/ChildDNSService.h
new file mode 100644
index 000000000..1662960bb
--- /dev/null
+++ b/netwerk/dns/ChildDNSService.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_net_ChildDNSService_h
+#define mozilla_net_ChildDNSService_h
+
+
+#include "nsPIDNSService.h"
+#include "nsIObserver.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Mutex.h"
+#include "DNSRequestChild.h"
+#include "nsHashKeys.h"
+#include "nsClassHashtable.h"
+
+namespace mozilla {
+namespace net {
+
+class ChildDNSService final
+ : public nsPIDNSService
+ , public nsIObserver
+{
+public:
+ // AsyncResolve (and CancelAsyncResolve) can be called off-main
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSPIDNSSERVICE
+ NS_DECL_NSIDNSSERVICE
+ NS_DECL_NSIOBSERVER
+
+ ChildDNSService();
+
+ static ChildDNSService* GetSingleton();
+
+ void NotifyRequestDone(DNSRequestChild *aDnsRequest);
+
+ bool GetOffline() const;
+private:
+ virtual ~ChildDNSService();
+
+ void MOZ_ALWAYS_INLINE GetDNSRecordHashKey(const nsACString &aHost,
+ uint32_t aFlags,
+ const nsACString &aNetworkInterface,
+ nsIDNSListener* aListener,
+ nsACString &aHashKey);
+
+ bool mFirstTime;
+ bool mDisablePrefetch;
+
+ // We need to remember pending dns requests to be able to cancel them.
+ nsClassHashtable<nsCStringHashKey, nsTArray<RefPtr<DNSRequestChild>>> mPendingRequests;
+ Mutex mPendingRequestsLock;
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif // mozilla_net_ChildDNSService_h
diff --git a/netwerk/dns/DNS.cpp b/netwerk/dns/DNS.cpp
new file mode 100644
index 000000000..643296af0
--- /dev/null
+++ b/netwerk/dns/DNS.cpp
@@ -0,0 +1,368 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/net/DNS.h"
+
+#include "mozilla/Assertions.h"
+#include "mozilla/mozalloc.h"
+#include "mozilla/ArrayUtils.h"
+#include <string.h>
+
+#ifdef XP_WIN
+#include "ws2tcpip.h"
+#endif
+
+namespace mozilla {
+namespace net {
+
+const char *inet_ntop_internal(int af, const void *src, char *dst, socklen_t size)
+{
+#ifdef XP_WIN
+ if (af == AF_INET) {
+ struct sockaddr_in s;
+ memset(&s, 0, sizeof(s));
+ s.sin_family = AF_INET;
+ memcpy(&s.sin_addr, src, sizeof(struct in_addr));
+ int result = getnameinfo((struct sockaddr *)&s, sizeof(struct sockaddr_in),
+ dst, size, nullptr, 0, NI_NUMERICHOST);
+ if (result == 0) {
+ return dst;
+ }
+ }
+ else if (af == AF_INET6) {
+ struct sockaddr_in6 s;
+ memset(&s, 0, sizeof(s));
+ s.sin6_family = AF_INET6;
+ memcpy(&s.sin6_addr, src, sizeof(struct in_addr6));
+ int result = getnameinfo((struct sockaddr *)&s, sizeof(struct sockaddr_in6),
+ dst, size, nullptr, 0, NI_NUMERICHOST);
+ if (result == 0) {
+ return dst;
+ }
+ }
+ return nullptr;
+#else
+ return inet_ntop(af, src, dst, size);
+#endif
+}
+
+// Copies the contents of a PRNetAddr to a NetAddr.
+// Does not do a ptr safety check!
+void PRNetAddrToNetAddr(const PRNetAddr *prAddr, NetAddr *addr)
+{
+ if (prAddr->raw.family == PR_AF_INET) {
+ addr->inet.family = AF_INET;
+ addr->inet.port = prAddr->inet.port;
+ addr->inet.ip = prAddr->inet.ip;
+ }
+ else if (prAddr->raw.family == PR_AF_INET6) {
+ addr->inet6.family = AF_INET6;
+ addr->inet6.port = prAddr->ipv6.port;
+ addr->inet6.flowinfo = prAddr->ipv6.flowinfo;
+ memcpy(&addr->inet6.ip, &prAddr->ipv6.ip, sizeof(addr->inet6.ip.u8));
+ addr->inet6.scope_id = prAddr->ipv6.scope_id;
+ }
+#if defined(XP_UNIX)
+ else if (prAddr->raw.family == PR_AF_LOCAL) {
+ addr->local.family = AF_LOCAL;
+ memcpy(addr->local.path, prAddr->local.path, sizeof(addr->local.path));
+ }
+#endif
+}
+
+// Copies the contents of a NetAddr to a PRNetAddr.
+// Does not do a ptr safety check!
+void NetAddrToPRNetAddr(const NetAddr *addr, PRNetAddr *prAddr)
+{
+ if (addr->raw.family == AF_INET) {
+ prAddr->inet.family = PR_AF_INET;
+ prAddr->inet.port = addr->inet.port;
+ prAddr->inet.ip = addr->inet.ip;
+ }
+ else if (addr->raw.family == AF_INET6) {
+ prAddr->ipv6.family = PR_AF_INET6;
+ prAddr->ipv6.port = addr->inet6.port;
+ prAddr->ipv6.flowinfo = addr->inet6.flowinfo;
+ memcpy(&prAddr->ipv6.ip, &addr->inet6.ip, sizeof(addr->inet6.ip.u8));
+ prAddr->ipv6.scope_id = addr->inet6.scope_id;
+ }
+#if defined(XP_UNIX)
+ else if (addr->raw.family == AF_LOCAL) {
+ prAddr->local.family = PR_AF_LOCAL;
+ memcpy(prAddr->local.path, addr->local.path, sizeof(addr->local.path));
+ }
+#elif defined(XP_WIN)
+ else if (addr->raw.family == AF_LOCAL) {
+ prAddr->local.family = PR_AF_LOCAL;
+ memcpy(prAddr->local.path, addr->local.path, sizeof(addr->local.path));
+ }
+#endif
+}
+
+bool NetAddrToString(const NetAddr *addr, char *buf, uint32_t bufSize)
+{
+ if (addr->raw.family == AF_INET) {
+ if (bufSize < INET_ADDRSTRLEN) {
+ return false;
+ }
+ struct in_addr nativeAddr = {};
+ nativeAddr.s_addr = addr->inet.ip;
+ return !!inet_ntop_internal(AF_INET, &nativeAddr, buf, bufSize);
+ }
+ else if (addr->raw.family == AF_INET6) {
+ if (bufSize < INET6_ADDRSTRLEN) {
+ return false;
+ }
+ struct in6_addr nativeAddr = {};
+ memcpy(&nativeAddr.s6_addr, &addr->inet6.ip, sizeof(addr->inet6.ip.u8));
+ return !!inet_ntop_internal(AF_INET6, &nativeAddr, buf, bufSize);
+ }
+#if defined(XP_UNIX)
+ else if (addr->raw.family == AF_LOCAL) {
+ if (bufSize < sizeof(addr->local.path)) {
+ // Many callers don't bother checking our return value, so
+ // null-terminate just in case.
+ if (bufSize > 0) {
+ buf[0] = '\0';
+ }
+ return false;
+ }
+
+ // Usually, the size passed to memcpy should be the size of the
+ // destination. Here, we know that the source is no larger than the
+ // destination, so using the source's size is always safe, whereas
+ // using the destination's size may cause us to read off the end of the
+ // source.
+ memcpy(buf, addr->local.path, sizeof(addr->local.path));
+ return true;
+ }
+#endif
+ return false;
+}
+
+bool IsLoopBackAddress(const NetAddr *addr)
+{
+ if (addr->raw.family == AF_INET) {
+ return (addr->inet.ip == htonl(INADDR_LOOPBACK));
+ }
+ else if (addr->raw.family == AF_INET6) {
+ if (IPv6ADDR_IS_LOOPBACK(&addr->inet6.ip)) {
+ return true;
+ } else if (IPv6ADDR_IS_V4MAPPED(&addr->inet6.ip) &&
+ IPv6ADDR_V4MAPPED_TO_IPADDR(&addr->inet6.ip) == htonl(INADDR_LOOPBACK)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool IsIPAddrAny(const NetAddr *addr)
+{
+ if (addr->raw.family == AF_INET) {
+ if (addr->inet.ip == htonl(INADDR_ANY)) {
+ return true;
+ }
+ }
+ else if (addr->raw.family == AF_INET6) {
+ if (IPv6ADDR_IS_UNSPECIFIED(&addr->inet6.ip)) {
+ return true;
+ } else if (IPv6ADDR_IS_V4MAPPED(&addr->inet6.ip) &&
+ IPv6ADDR_V4MAPPED_TO_IPADDR(&addr->inet6.ip) == htonl(INADDR_ANY)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool IsIPAddrV4Mapped(const NetAddr *addr)
+{
+ if (addr->raw.family == AF_INET6) {
+ return IPv6ADDR_IS_V4MAPPED(&addr->inet6.ip);
+ }
+ return false;
+}
+
+bool IsIPAddrLocal(const NetAddr *addr)
+{
+ MOZ_ASSERT(addr);
+
+ // IPv4 RFC1918 and Link Local Addresses.
+ if (addr->raw.family == AF_INET) {
+ uint32_t addr32 = ntohl(addr->inet.ip);
+ if (addr32 >> 24 == 0x0A || // 10/8 prefix (RFC 1918).
+ addr32 >> 20 == 0xAC1 || // 172.16/12 prefix (RFC 1918).
+ addr32 >> 16 == 0xC0A8 || // 192.168/16 prefix (RFC 1918).
+ addr32 >> 16 == 0xA9FE) { // 169.254/16 prefix (Link Local).
+ return true;
+ }
+ }
+ // IPv6 Unique and Link Local Addresses.
+ if (addr->raw.family == AF_INET6) {
+ uint16_t addr16 = ntohs(addr->inet6.ip.u16[0]);
+ if (addr16 >> 9 == 0xfc >> 1 || // fc00::/7 Unique Local Address.
+ addr16 >> 6 == 0xfe80 >> 6) { // fe80::/10 Link Local Address.
+ return true;
+ }
+ }
+ // Not an IPv4/6 local address.
+ return false;
+}
+
+nsresult
+GetPort(const NetAddr *aAddr, uint16_t *aResult)
+{
+ uint16_t port;
+ if (aAddr->raw.family == PR_AF_INET) {
+ port = aAddr->inet.port;
+ } else if (aAddr->raw.family == PR_AF_INET6) {
+ port = aAddr->inet6.port;
+ } else {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ *aResult = ntohs(port);
+ return NS_OK;
+}
+
+bool
+NetAddr::operator == (const NetAddr& other) const
+{
+ if (this->raw.family != other.raw.family) {
+ return false;
+ } else if (this->raw.family == AF_INET) {
+ return (this->inet.port == other.inet.port) &&
+ (this->inet.ip == other.inet.ip);
+ } else if (this->raw.family == AF_INET6) {
+ return (this->inet6.port == other.inet6.port) &&
+ (this->inet6.flowinfo == other.inet6.flowinfo) &&
+ (memcmp(&this->inet6.ip, &other.inet6.ip,
+ sizeof(this->inet6.ip)) == 0) &&
+ (this->inet6.scope_id == other.inet6.scope_id);
+#if defined(XP_UNIX)
+ } else if (this->raw.family == AF_LOCAL) {
+ return PL_strncmp(this->local.path, other.local.path,
+ ArrayLength(this->local.path));
+#endif
+ }
+ return false;
+}
+
+bool
+NetAddr::operator < (const NetAddr& other) const
+{
+ if (this->raw.family != other.raw.family) {
+ return this->raw.family < other.raw.family;
+ } else if (this->raw.family == AF_INET) {
+ if (this->inet.ip == other.inet.ip) {
+ return this->inet.port < other.inet.port;
+ } else {
+ return this->inet.ip < other.inet.ip;
+ }
+ } else if (this->raw.family == AF_INET6) {
+ int cmpResult = memcmp(&this->inet6.ip, &other.inet6.ip,
+ sizeof(this->inet6.ip));
+ if (cmpResult) {
+ return cmpResult < 0;
+ } else if (this->inet6.port != other.inet6.port) {
+ return this->inet6.port < other.inet6.port;
+ } else {
+ return this->inet6.flowinfo < other.inet6.flowinfo;
+ }
+ }
+ return false;
+}
+
+NetAddrElement::NetAddrElement(const PRNetAddr *prNetAddr)
+{
+ PRNetAddrToNetAddr(prNetAddr, &mAddress);
+}
+
+NetAddrElement::NetAddrElement(const NetAddrElement& netAddr)
+{
+ mAddress = netAddr.mAddress;
+}
+
+NetAddrElement::~NetAddrElement() = default;
+
+AddrInfo::AddrInfo(const char *host, const PRAddrInfo *prAddrInfo,
+ bool disableIPv4, bool filterNameCollision, const char *cname)
+ : mHostName(nullptr)
+ , mCanonicalName(nullptr)
+ , ttl(NO_TTL_DATA)
+{
+ MOZ_ASSERT(prAddrInfo, "Cannot construct AddrInfo with a null prAddrInfo pointer!");
+ const uint32_t nameCollisionAddr = htonl(0x7f003535); // 127.0.53.53
+
+ Init(host, cname);
+ PRNetAddr tmpAddr;
+ void *iter = nullptr;
+ do {
+ iter = PR_EnumerateAddrInfo(iter, prAddrInfo, 0, &tmpAddr);
+ bool addIt = iter &&
+ (!disableIPv4 || tmpAddr.raw.family != PR_AF_INET) &&
+ (!filterNameCollision || tmpAddr.raw.family != PR_AF_INET || (tmpAddr.inet.ip != nameCollisionAddr));
+ if (addIt) {
+ auto *addrElement = new NetAddrElement(&tmpAddr);
+ mAddresses.insertBack(addrElement);
+ }
+ } while (iter);
+}
+
+AddrInfo::AddrInfo(const char *host, const char *cname)
+ : mHostName(nullptr)
+ , mCanonicalName(nullptr)
+ , ttl(NO_TTL_DATA)
+{
+ Init(host, cname);
+}
+
+AddrInfo::~AddrInfo()
+{
+ NetAddrElement *addrElement;
+ while ((addrElement = mAddresses.popLast())) {
+ delete addrElement;
+ }
+ free(mHostName);
+ free(mCanonicalName);
+}
+
+void
+AddrInfo::Init(const char *host, const char *cname)
+{
+ MOZ_ASSERT(host, "Cannot initialize AddrInfo with a null host pointer!");
+
+ ttl = NO_TTL_DATA;
+ size_t hostlen = strlen(host);
+ mHostName = static_cast<char*>(moz_xmalloc(hostlen + 1));
+ memcpy(mHostName, host, hostlen + 1);
+ if (cname) {
+ size_t cnameLen = strlen(cname);
+ mCanonicalName = static_cast<char*>(moz_xmalloc(cnameLen + 1));
+ memcpy(mCanonicalName, cname, cnameLen + 1);
+ }
+ else {
+ mCanonicalName = nullptr;
+ }
+}
+
+void
+AddrInfo::AddAddress(NetAddrElement *address)
+{
+ MOZ_ASSERT(address, "Cannot add the address to an uninitialized list");
+
+ mAddresses.insertBack(address);
+}
+
+size_t
+AddrInfo::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const
+{
+ size_t n = mallocSizeOf(this);
+ n += mallocSizeOf(mHostName);
+ n += mallocSizeOf(mCanonicalName);
+ n += mAddresses.sizeOfExcludingThis(mallocSizeOf);
+ return n;
+}
+
+} // namespace net
+} // namespace mozilla
diff --git a/netwerk/dns/DNS.h b/netwerk/dns/DNS.h
new file mode 100644
index 000000000..22e1f31f1
--- /dev/null
+++ b/netwerk/dns/DNS.h
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef DNS_h_
+#define DNS_h_
+
+#include "nscore.h"
+#include "prio.h"
+#include "prnetdb.h"
+#include "plstr.h"
+#include "mozilla/LinkedList.h"
+#include "mozilla/MemoryReporting.h"
+
+#if !defined(XP_WIN)
+#include <arpa/inet.h>
+#endif
+
+#ifdef XP_WIN
+#include "winsock2.h"
+#endif
+
+#ifndef AF_LOCAL
+#define AF_LOCAL 1 // used for named pipe
+#endif
+
+#define IPv6ADDR_IS_LOOPBACK(a) \
+ (((a)->u32[0] == 0) && \
+ ((a)->u32[1] == 0) && \
+ ((a)->u32[2] == 0) && \
+ ((a)->u8[12] == 0) && \
+ ((a)->u8[13] == 0) && \
+ ((a)->u8[14] == 0) && \
+ ((a)->u8[15] == 0x1U))
+
+#define IPv6ADDR_IS_V4MAPPED(a) \
+ (((a)->u32[0] == 0) && \
+ ((a)->u32[1] == 0) && \
+ ((a)->u8[8] == 0) && \
+ ((a)->u8[9] == 0) && \
+ ((a)->u8[10] == 0xff) && \
+ ((a)->u8[11] == 0xff))
+
+#define IPv6ADDR_V4MAPPED_TO_IPADDR(a) ((a)->u32[3])
+
+#define IPv6ADDR_IS_UNSPECIFIED(a) \
+ (((a)->u32[0] == 0) && \
+ ((a)->u32[1] == 0) && \
+ ((a)->u32[2] == 0) && \
+ ((a)->u32[3] == 0))
+
+namespace mozilla {
+namespace net {
+
+// Required buffer size for text form of an IP address.
+// Includes space for null termination. We make our own contants
+// because we don't want higher-level code depending on things
+// like INET6_ADDRSTRLEN and having to include the associated
+// platform-specific headers.
+#ifdef XP_WIN
+// Windows requires longer buffers for some reason.
+const int kIPv4CStrBufSize = 22;
+const int kIPv6CStrBufSize = 65;
+const int kNetAddrMaxCStrBufSize = kIPv6CStrBufSize;
+#else
+const int kIPv4CStrBufSize = 16;
+const int kIPv6CStrBufSize = 46;
+const int kLocalCStrBufSize = 108;
+const int kNetAddrMaxCStrBufSize = kLocalCStrBufSize;
+#endif
+
+// This was all created at a time in which we were using NSPR for host
+// resolution and we were propagating NSPR types like "PRAddrInfo" and
+// "PRNetAddr" all over Gecko. This made it hard to use another host
+// resolver -- we were locked into NSPR. The goal here is to get away
+// from that. We'll translate what we get from NSPR or any other host
+// resolution library into the types below and use them in Gecko.
+
+union IPv6Addr {
+ uint8_t u8[16];
+ uint16_t u16[8];
+ uint32_t u32[4];
+ uint64_t u64[2];
+};
+
+// This struct is similar to operating system structs like "sockaddr", used for
+// things like "connect" and "getsockname". When tempted to cast or do dumb
+// copies of this struct to another struct, bear compiler-computed padding
+// in mind. The size of this struct, and the layout of the data in it, may
+// not be what you expect.
+union NetAddr {
+ struct {
+ uint16_t family; /* address family (0x00ff maskable) */
+ char data[14]; /* raw address data */
+ } raw;
+ struct {
+ uint16_t family; /* address family (AF_INET) */
+ uint16_t port; /* port number */
+ uint32_t ip; /* The actual 32 bits of address */
+ } inet;
+ struct {
+ uint16_t family; /* address family (AF_INET6) */
+ uint16_t port; /* port number */
+ uint32_t flowinfo; /* routing information */
+ IPv6Addr ip; /* the actual 128 bits of address */
+ uint32_t scope_id; /* set of interfaces for a scope */
+ } inet6;
+#if defined(XP_UNIX) || defined(XP_WIN)
+ struct { /* Unix domain socket or
+ Windows Named Pipes address */
+ uint16_t family; /* address family (AF_UNIX) */
+ char path[104]; /* null-terminated pathname */
+ } local;
+#endif
+ // introduced to support nsTArray<NetAddr> comparisons and sorting
+ bool operator == (const NetAddr& other) const;
+ bool operator < (const NetAddr &other) const;
+};
+
+// This class wraps a NetAddr union to provide C++ linked list
+// capabilities and other methods. It is created from a PRNetAddr,
+// which is converted to a mozilla::dns::NetAddr.
+class NetAddrElement : public LinkedListElement<NetAddrElement> {
+public:
+ explicit NetAddrElement(const PRNetAddr *prNetAddr);
+ NetAddrElement(const NetAddrElement& netAddr);
+ ~NetAddrElement();
+
+ NetAddr mAddress;
+};
+
+class AddrInfo {
+public:
+ // Creates an AddrInfo object. It calls the AddrInfo(const char*, const char*)
+ // to initialize the host and the cname.
+ AddrInfo(const char *host, const PRAddrInfo *prAddrInfo, bool disableIPv4,
+ bool filterNameCollision, const char *cname);
+
+ // Creates a basic AddrInfo object (initialize only the host and the cname).
+ AddrInfo(const char *host, const char *cname);
+ ~AddrInfo();
+
+ void AddAddress(NetAddrElement *address);
+
+ size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
+
+ char *mHostName;
+ char *mCanonicalName;
+ uint16_t ttl;
+ static const uint16_t NO_TTL_DATA = (uint16_t) -1;
+
+ LinkedList<NetAddrElement> mAddresses;
+
+private:
+ void Init(const char *host, const char *cname);
+};
+
+// Copies the contents of a PRNetAddr to a NetAddr.
+// Does not do a ptr safety check!
+void PRNetAddrToNetAddr(const PRNetAddr *prAddr, NetAddr *addr);
+
+// Copies the contents of a NetAddr to a PRNetAddr.
+// Does not do a ptr safety check!
+void NetAddrToPRNetAddr(const NetAddr *addr, PRNetAddr *prAddr);
+
+bool NetAddrToString(const NetAddr *addr, char *buf, uint32_t bufSize);
+
+bool IsLoopBackAddress(const NetAddr *addr);
+
+bool IsIPAddrAny(const NetAddr *addr);
+
+bool IsIPAddrV4Mapped(const NetAddr *addr);
+
+bool IsIPAddrLocal(const NetAddr *addr);
+
+nsresult GetPort(const NetAddr *aAddr, uint16_t *aResult);
+
+} // namespace net
+} // namespace mozilla
+
+#endif // DNS_h_
diff --git a/netwerk/dns/DNSListenerProxy.cpp b/netwerk/dns/DNSListenerProxy.cpp
new file mode 100644
index 000000000..333f0946d
--- /dev/null
+++ b/netwerk/dns/DNSListenerProxy.cpp
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set sw=4 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/net/DNSListenerProxy.h"
+#include "nsICancelable.h"
+#include "nsIEventTarget.h"
+
+namespace mozilla {
+namespace net {
+
+NS_IMPL_ISUPPORTS(DNSListenerProxy,
+ nsIDNSListener,
+ nsIDNSListenerProxy)
+
+NS_IMETHODIMP
+DNSListenerProxy::OnLookupComplete(nsICancelable* aRequest,
+ nsIDNSRecord* aRecord,
+ nsresult aStatus)
+{
+ RefPtr<OnLookupCompleteRunnable> r =
+ new OnLookupCompleteRunnable(mListener, aRequest, aRecord, aStatus);
+ return mTargetThread->Dispatch(r, NS_DISPATCH_NORMAL);
+}
+
+NS_IMETHODIMP
+DNSListenerProxy::OnLookupCompleteRunnable::Run()
+{
+ mListener->OnLookupComplete(mRequest, mRecord, mStatus);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+DNSListenerProxy::GetOriginalListener(nsIDNSListener **aOriginalListener)
+{
+ NS_IF_ADDREF(*aOriginalListener = mListener);
+ return NS_OK;
+}
+
+} // namespace net
+} // namespace mozilla
diff --git a/netwerk/dns/DNSListenerProxy.h b/netwerk/dns/DNSListenerProxy.h
new file mode 100644
index 000000000..307dde0f7
--- /dev/null
+++ b/netwerk/dns/DNSListenerProxy.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set sw=4 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef DNSListenerProxy_h__
+#define DNSListenerProxy_h__
+
+#include "nsIDNSListener.h"
+#include "nsIDNSRecord.h"
+#include "nsProxyRelease.h"
+#include "nsThreadUtils.h"
+
+class nsIEventTarget;
+class nsICancelable;
+
+namespace mozilla {
+namespace net {
+
+class DNSListenerProxy final
+ : public nsIDNSListener
+ , public nsIDNSListenerProxy
+{
+public:
+ DNSListenerProxy(nsIDNSListener* aListener, nsIEventTarget* aTargetThread)
+ // Sometimes aListener is a main-thread only object like XPCWrappedJS, and
+ // sometimes it's a threadsafe object like nsSOCKSSocketInfo. Use a main-
+ // thread pointer holder, but disable strict enforcement of thread invariants.
+ // The AddRef implementation of XPCWrappedJS will assert if we go wrong here.
+ : mListener(new nsMainThreadPtrHolder<nsIDNSListener>(aListener, false))
+ , mTargetThread(aTargetThread)
+ { }
+
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIDNSLISTENER
+ NS_DECL_NSIDNSLISTENERPROXY
+
+ class OnLookupCompleteRunnable : public Runnable
+ {
+ public:
+ OnLookupCompleteRunnable(const nsMainThreadPtrHandle<nsIDNSListener>& aListener,
+ nsICancelable* aRequest,
+ nsIDNSRecord* aRecord,
+ nsresult aStatus)
+ : mListener(aListener)
+ , mRequest(aRequest)
+ , mRecord(aRecord)
+ , mStatus(aStatus)
+ { }
+
+ NS_DECL_NSIRUNNABLE
+
+ private:
+ nsMainThreadPtrHandle<nsIDNSListener> mListener;
+ nsCOMPtr<nsICancelable> mRequest;
+ nsCOMPtr<nsIDNSRecord> mRecord;
+ nsresult mStatus;
+ };
+
+private:
+ ~DNSListenerProxy() {}
+
+ nsMainThreadPtrHandle<nsIDNSListener> mListener;
+ nsCOMPtr<nsIEventTarget> mTargetThread;
+};
+
+
+} // namespace net
+} // namespace mozilla
+
+#endif // DNSListenerProxy_h__
diff --git a/netwerk/dns/DNSRequestChild.cpp b/netwerk/dns/DNSRequestChild.cpp
new file mode 100644
index 000000000..84086202b
--- /dev/null
+++ b/netwerk/dns/DNSRequestChild.cpp
@@ -0,0 +1,313 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/net/ChildDNSService.h"
+#include "mozilla/net/DNSRequestChild.h"
+#include "mozilla/net/NeckoChild.h"
+#include "mozilla/Unused.h"
+#include "nsIDNSRecord.h"
+#include "nsHostResolver.h"
+#include "nsTArray.h"
+#include "nsNetAddr.h"
+#include "nsIThread.h"
+#include "nsThreadUtils.h"
+
+using namespace mozilla::ipc;
+
+namespace mozilla {
+namespace net {
+
+//-----------------------------------------------------------------------------
+// ChildDNSRecord:
+// A simple class to provide nsIDNSRecord on the child
+//-----------------------------------------------------------------------------
+
+class ChildDNSRecord : public nsIDNSRecord
+{
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIDNSRECORD
+
+ ChildDNSRecord(const DNSRecord& reply, uint16_t flags);
+
+private:
+ virtual ~ChildDNSRecord();
+
+ nsCString mCanonicalName;
+ nsTArray<NetAddr> mAddresses;
+ uint32_t mCurrent; // addr iterator
+ uint32_t mLength; // number of addrs
+ uint16_t mFlags;
+};
+
+NS_IMPL_ISUPPORTS(ChildDNSRecord, nsIDNSRecord)
+
+ChildDNSRecord::ChildDNSRecord(const DNSRecord& reply, uint16_t flags)
+ : mCurrent(0)
+ , mFlags(flags)
+{
+ mCanonicalName = reply.canonicalName();
+
+ // A shame IPDL gives us no way to grab ownership of array: so copy it.
+ const nsTArray<NetAddr>& addrs = reply.addrs();
+ uint32_t i = 0;
+ mLength = addrs.Length();
+ for (; i < mLength; i++) {
+ mAddresses.AppendElement(addrs[i]);
+ }
+}
+
+ChildDNSRecord::~ChildDNSRecord()
+{
+}
+
+//-----------------------------------------------------------------------------
+// ChildDNSRecord::nsIDNSRecord
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+ChildDNSRecord::GetCanonicalName(nsACString &result)
+{
+ if (!(mFlags & nsHostResolver::RES_CANON_NAME)) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ result = mCanonicalName;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ChildDNSRecord::GetNextAddr(uint16_t port, NetAddr *addr)
+{
+ if (mCurrent >= mLength) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ memcpy(addr, &mAddresses[mCurrent++], sizeof(NetAddr));
+
+ // both Ipv4/6 use same bits for port, so safe to just use ipv4's field
+ addr->inet.port = htons(port);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ChildDNSRecord::GetAddresses(nsTArray<NetAddr> & aAddressArray)
+{
+ aAddressArray = mAddresses;
+ return NS_OK;
+}
+
+// shamelessly copied from nsDNSRecord
+NS_IMETHODIMP
+ChildDNSRecord::GetScriptableNextAddr(uint16_t port, nsINetAddr **result)
+{
+ NetAddr addr;
+ nsresult rv = GetNextAddr(port, &addr);
+ if (NS_FAILED(rv)) return rv;
+
+ NS_ADDREF(*result = new nsNetAddr(&addr));
+
+ return NS_OK;
+}
+
+// also copied from nsDNSRecord
+NS_IMETHODIMP
+ChildDNSRecord::GetNextAddrAsString(nsACString &result)
+{
+ NetAddr addr;
+ nsresult rv = GetNextAddr(0, &addr);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ char buf[kIPv6CStrBufSize];
+ if (NetAddrToString(&addr, buf, sizeof(buf))) {
+ result.Assign(buf);
+ return NS_OK;
+ }
+ NS_ERROR("NetAddrToString failed unexpectedly");
+ return NS_ERROR_FAILURE; // conversion failed for some reason
+}
+
+NS_IMETHODIMP
+ChildDNSRecord::HasMore(bool *result)
+{
+ *result = mCurrent < mLength;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ChildDNSRecord::Rewind()
+{
+ mCurrent = 0;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+ChildDNSRecord::ReportUnusable(uint16_t aPort)
+{
+ // "We thank you for your feedback" == >/dev/null
+ // TODO: we could send info back to parent.
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+// CancelDNSRequestEvent
+//-----------------------------------------------------------------------------
+
+class CancelDNSRequestEvent : public Runnable
+{
+public:
+ CancelDNSRequestEvent(DNSRequestChild* aDnsReq, nsresult aReason)
+ : mDnsRequest(aDnsReq)
+ , mReasonForCancel(aReason)
+ {}
+
+ NS_IMETHOD Run() override
+ {
+ if (mDnsRequest->mIPCOpen) {
+ // Send request to Parent process.
+ mDnsRequest->SendCancelDNSRequest(mDnsRequest->mHost, mDnsRequest->mFlags,
+ mDnsRequest->mNetworkInterface,
+ mReasonForCancel);
+ }
+ return NS_OK;
+ }
+private:
+ RefPtr<DNSRequestChild> mDnsRequest;
+ nsresult mReasonForCancel;
+};
+
+//-----------------------------------------------------------------------------
+// DNSRequestChild
+//-----------------------------------------------------------------------------
+
+DNSRequestChild::DNSRequestChild(const nsCString& aHost,
+ const uint32_t& aFlags,
+ const nsCString& aNetworkInterface,
+ nsIDNSListener *aListener,
+ nsIEventTarget *target)
+ : mListener(aListener)
+ , mTarget(target)
+ , mResultStatus(NS_OK)
+ , mHost(aHost)
+ , mFlags(aFlags)
+ , mNetworkInterface(aNetworkInterface)
+ , mIPCOpen(false)
+{
+}
+
+void
+DNSRequestChild::StartRequest()
+{
+ // we can only do IPDL on the main thread
+ if (!NS_IsMainThread()) {
+ NS_DispatchToMainThread(
+ NewRunnableMethod(this, &DNSRequestChild::StartRequest));
+ return;
+ }
+
+ // Send request to Parent process.
+ gNeckoChild->SendPDNSRequestConstructor(this, mHost, mFlags,
+ mNetworkInterface);
+ mIPCOpen = true;
+
+ // IPDL holds a reference until IPDL channel gets destroyed
+ AddIPDLReference();
+}
+
+void
+DNSRequestChild::CallOnLookupComplete()
+{
+ MOZ_ASSERT(mListener);
+ mListener->OnLookupComplete(this, mResultRecord, mResultStatus);
+}
+
+bool
+DNSRequestChild::RecvLookupCompleted(const DNSRequestResponse& reply)
+{
+ mIPCOpen = false;
+ MOZ_ASSERT(mListener);
+
+ switch (reply.type()) {
+ case DNSRequestResponse::TDNSRecord: {
+ mResultRecord = new ChildDNSRecord(reply.get_DNSRecord(), mFlags);
+ break;
+ }
+ case DNSRequestResponse::Tnsresult: {
+ mResultStatus = reply.get_nsresult();
+ break;
+ }
+ default:
+ NS_NOTREACHED("unknown type");
+ return false;
+ }
+
+ MOZ_ASSERT(NS_IsMainThread());
+
+ bool targetIsMain = false;
+ if (!mTarget) {
+ targetIsMain = true;
+ } else {
+ mTarget->IsOnCurrentThread(&targetIsMain);
+ }
+
+ if (targetIsMain) {
+ CallOnLookupComplete();
+ } else {
+ nsCOMPtr<nsIRunnable> event =
+ NewRunnableMethod(this, &DNSRequestChild::CallOnLookupComplete);
+ mTarget->Dispatch(event, NS_DISPATCH_NORMAL);
+ }
+
+ Unused << Send__delete__(this);
+
+ return true;
+}
+
+void
+DNSRequestChild::ReleaseIPDLReference()
+{
+ // Request is done or destroyed. Remove it from the hash table.
+ RefPtr<ChildDNSService> dnsServiceChild =
+ dont_AddRef(ChildDNSService::GetSingleton());
+ dnsServiceChild->NotifyRequestDone(this);
+
+ Release();
+}
+
+void
+DNSRequestChild::ActorDestroy(ActorDestroyReason why)
+{
+ mIPCOpen = false;
+}
+
+//-----------------------------------------------------------------------------
+// DNSRequestChild::nsISupports
+//-----------------------------------------------------------------------------
+
+NS_IMPL_ISUPPORTS(DNSRequestChild,
+ nsICancelable)
+
+//-----------------------------------------------------------------------------
+// DNSRequestChild::nsICancelable
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+DNSRequestChild::Cancel(nsresult reason)
+{
+ if(mIPCOpen) {
+ // We can only do IPDL on the main thread
+ NS_DispatchToMainThread(
+ new CancelDNSRequestEvent(this, reason));
+ }
+ return NS_OK;
+}
+
+//------------------------------------------------------------------------------
+} // namespace net
+} // namespace mozilla
diff --git a/netwerk/dns/DNSRequestChild.h b/netwerk/dns/DNSRequestChild.h
new file mode 100644
index 000000000..26d4ff98d
--- /dev/null
+++ b/netwerk/dns/DNSRequestChild.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_net_DNSRequestChild_h
+#define mozilla_net_DNSRequestChild_h
+
+#include "mozilla/net/PDNSRequestChild.h"
+#include "nsICancelable.h"
+#include "nsIDNSRecord.h"
+#include "nsIDNSListener.h"
+#include "nsIEventTarget.h"
+
+namespace mozilla {
+namespace net {
+
+class DNSRequestChild final
+ : public PDNSRequestChild
+ , public nsICancelable
+{
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSICANCELABLE
+
+ DNSRequestChild(const nsCString& aHost, const uint32_t& aFlags,
+ const nsCString& aNetworkInterface,
+ nsIDNSListener *aListener, nsIEventTarget *target);
+
+ void AddIPDLReference() {
+ AddRef();
+ }
+ void ReleaseIPDLReference();
+
+ // Sends IPDL request to parent
+ void StartRequest();
+ void CallOnLookupComplete();
+
+protected:
+ friend class CancelDNSRequestEvent;
+ friend class ChildDNSService;
+ virtual ~DNSRequestChild() {}
+
+ virtual bool RecvLookupCompleted(const DNSRequestResponse& reply) override;
+ virtual void ActorDestroy(ActorDestroyReason why) override;
+
+ nsCOMPtr<nsIDNSListener> mListener;
+ nsCOMPtr<nsIEventTarget> mTarget;
+ nsCOMPtr<nsIDNSRecord> mResultRecord;
+ nsresult mResultStatus;
+ nsCString mHost;
+ uint16_t mFlags;
+ nsCString mNetworkInterface;
+ bool mIPCOpen;
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif // mozilla_net_DNSRequestChild_h
diff --git a/netwerk/dns/DNSRequestParent.cpp b/netwerk/dns/DNSRequestParent.cpp
new file mode 100644
index 000000000..a5c95a812
--- /dev/null
+++ b/netwerk/dns/DNSRequestParent.cpp
@@ -0,0 +1,132 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/net/DNSRequestParent.h"
+#include "nsIDNSService.h"
+#include "nsNetCID.h"
+#include "nsThreadUtils.h"
+#include "nsIServiceManager.h"
+#include "nsICancelable.h"
+#include "nsIDNSRecord.h"
+#include "nsHostResolver.h"
+#include "mozilla/Unused.h"
+
+using namespace mozilla::ipc;
+
+namespace mozilla {
+namespace net {
+
+DNSRequestParent::DNSRequestParent()
+ : mFlags(0)
+ , mIPCClosed(false)
+{
+
+}
+
+DNSRequestParent::~DNSRequestParent()
+{
+
+}
+
+void
+DNSRequestParent::DoAsyncResolve(const nsACString &hostname, uint32_t flags,
+ const nsACString &networkInterface)
+{
+ nsresult rv;
+ mFlags = flags;
+ nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv);
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
+ nsCOMPtr<nsICancelable> unused;
+ rv = dns->AsyncResolveExtended(hostname, flags, networkInterface, this,
+ mainThread, getter_AddRefs(unused));
+ }
+
+ if (NS_FAILED(rv) && !mIPCClosed) {
+ mIPCClosed = true;
+ Unused << SendLookupCompleted(DNSRequestResponse(rv));
+ }
+}
+
+bool
+DNSRequestParent::RecvCancelDNSRequest(const nsCString& hostName,
+ const uint32_t& flags,
+ const nsCString& networkInterface,
+ const nsresult& reason)
+{
+ nsresult rv;
+ nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv);
+ if (NS_SUCCEEDED(rv)) {
+ rv = dns->CancelAsyncResolveExtended(hostName, flags, networkInterface,
+ this, reason);
+ }
+ return true;
+}
+
+bool
+DNSRequestParent::Recv__delete__()
+{
+ mIPCClosed = true;
+ return true;
+}
+
+void
+DNSRequestParent::ActorDestroy(ActorDestroyReason why)
+{
+ // We may still have refcount>0 if DNS hasn't called our OnLookupComplete
+ // yet, but child process has crashed. We must not send any more msgs
+ // to child, or IPDL will kill chrome process, too.
+ mIPCClosed = true;
+}
+//-----------------------------------------------------------------------------
+// DNSRequestParent::nsISupports
+//-----------------------------------------------------------------------------
+
+NS_IMPL_ISUPPORTS(DNSRequestParent,
+ nsIDNSListener)
+
+//-----------------------------------------------------------------------------
+// nsIDNSListener functions
+//-----------------------------------------------------------------------------
+
+NS_IMETHODIMP
+DNSRequestParent::OnLookupComplete(nsICancelable *request,
+ nsIDNSRecord *rec,
+ nsresult status)
+{
+ if (mIPCClosed) {
+ // nothing to do: child probably crashed
+ return NS_OK;
+ }
+
+ if (NS_SUCCEEDED(status)) {
+ MOZ_ASSERT(rec);
+
+ nsAutoCString cname;
+ if (mFlags & nsHostResolver::RES_CANON_NAME) {
+ rec->GetCanonicalName(cname);
+ }
+
+ // Get IP addresses for hostname (use port 80 as dummy value for NetAddr)
+ NetAddrArray array;
+ NetAddr addr;
+ while (NS_SUCCEEDED(rec->GetNextAddr(80, &addr))) {
+ array.AppendElement(addr);
+ }
+
+ Unused << SendLookupCompleted(DNSRequestResponse(DNSRecord(cname, array)));
+ } else {
+ Unused << SendLookupCompleted(DNSRequestResponse(status));
+ }
+
+ mIPCClosed = true;
+ return NS_OK;
+}
+
+
+
+} // namespace net
+} // namespace mozilla
diff --git a/netwerk/dns/DNSRequestParent.h b/netwerk/dns/DNSRequestParent.h
new file mode 100644
index 000000000..d217dbd4f
--- /dev/null
+++ b/netwerk/dns/DNSRequestParent.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_net_DNSRequestParent_h
+#define mozilla_net_DNSRequestParent_h
+
+#include "mozilla/net/PDNSRequestParent.h"
+#include "nsIDNSService.h"
+#include "nsIDNSListener.h"
+
+namespace mozilla {
+namespace net {
+
+class DNSRequestParent
+ : public PDNSRequestParent
+ , public nsIDNSListener
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIDNSLISTENER
+
+ DNSRequestParent();
+
+ void DoAsyncResolve(const nsACString &hostname, uint32_t flags,
+ const nsACString &networkInterface);
+
+ // Pass args here rather than storing them in the parent; they are only
+ // needed if the request is to be canceled.
+ bool RecvCancelDNSRequest(const nsCString& hostName,
+ const uint32_t& flags,
+ const nsCString& networkInterface,
+ const nsresult& reason) override;
+ bool Recv__delete__() override;
+
+protected:
+ virtual void ActorDestroy(ActorDestroyReason why) override;
+private:
+ virtual ~DNSRequestParent();
+
+ uint32_t mFlags;
+ bool mIPCClosed; // true if IPDL channel has been closed (child crash)
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif // mozilla_net_DNSRequestParent_h
diff --git a/netwerk/dns/GetAddrInfo.cpp b/netwerk/dns/GetAddrInfo.cpp
new file mode 100644
index 000000000..3c177ec53
--- /dev/null
+++ b/netwerk/dns/GetAddrInfo.cpp
@@ -0,0 +1,369 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GetAddrInfo.h"
+#include "mozilla/net/DNS.h"
+#include "prnetdb.h"
+#include "nsHostResolver.h"
+#include "nsError.h"
+#include "mozilla/Mutex.h"
+#include "nsAutoPtr.h"
+#include "mozilla/StaticPtr.h"
+#include "MainThreadUtils.h"
+#include "mozilla/DebugOnly.h"
+#include "mozilla/net/DNS.h"
+#include <algorithm>
+#include "prerror.h"
+
+#include "mozilla/Logging.h"
+
+#if DNSQUERY_AVAILABLE
+// There is a bug in windns.h where the type of parameter ppQueryResultsSet for
+// DnsQuery_A is dependent on UNICODE being set. It should *always* be
+// PDNS_RECORDA, but if UNICODE is set it is PDNS_RECORDW. To get around this
+// we make sure that UNICODE is unset.
+#undef UNICODE
+#include <ws2tcpip.h>
+#undef GetAddrInfo
+#include <windns.h>
+#endif
+
+namespace mozilla {
+namespace net {
+
+static LazyLogModule gGetAddrInfoLog("GetAddrInfo");
+#define LOG(msg, ...) \
+ MOZ_LOG(gGetAddrInfoLog, LogLevel::Debug, ("[DNS]: " msg, ##__VA_ARGS__))
+#define LOG_WARNING(msg, ...) \
+ MOZ_LOG(gGetAddrInfoLog, LogLevel::Warning, ("[DNS]: " msg, ##__VA_ARGS__))
+
+#if DNSQUERY_AVAILABLE
+////////////////////////////
+// WINDOWS IMPLEMENTATION //
+////////////////////////////
+
+// Ensure consistency of PR_* and AF_* constants to allow for legacy usage of
+// PR_* constants with this API.
+static_assert(PR_AF_INET == AF_INET && PR_AF_INET6 == AF_INET6
+ && PR_AF_UNSPEC == AF_UNSPEC, "PR_AF_* must match AF_*");
+
+// We intentionally leak this mutex. This is because we can run into a
+// situation where the worker threads are still running until the process
+// is actually fully shut down, and at any time one of those worker
+// threads can access gDnsapiInfoLock.
+static OffTheBooksMutex* gDnsapiInfoLock = nullptr;
+
+struct DnsapiInfo
+{
+public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DnsapiInfo);
+
+ HMODULE mLibrary;
+ decltype(&DnsQuery_A) mDnsQueryFunc;
+ decltype(&DnsFree) mDnsFreeFunc;
+
+private:
+ // This will either be called during shutdown of the GetAddrInfo module, or
+ // when a worker thread is done doing a lookup (ie: within
+ // _GetAddrInfo_Windows). Note that the lock must be held when this is
+ // called.
+ ~DnsapiInfo()
+ {
+ if (gDnsapiInfoLock) {
+ gDnsapiInfoLock->AssertCurrentThreadOwns();
+ } else {
+ MOZ_ASSERT_UNREACHABLE("No mutex available during GetAddrInfo "
+ "shutdown.");
+ return;
+ }
+
+ LOG("Freeing Dnsapi.dll");
+ MOZ_ASSERT(mLibrary);
+ DebugOnly<BOOL> rv = FreeLibrary(mLibrary);
+ NS_WARNING_ASSERTION(rv, "Failed to free Dnsapi.dll.");
+ }
+};
+
+static StaticRefPtr<DnsapiInfo> gDnsapiInfo;
+
+static MOZ_ALWAYS_INLINE nsresult
+_GetAddrInfoInit_Windows()
+{
+ // This is necessary to ensure strict thread safety because if two threads
+ // run this function at the same time they can potentially create two
+ // mutexes.
+ MOZ_ASSERT(NS_IsMainThread(),
+ "Do not initialize GetAddrInfo off main thread!");
+
+ if (!gDnsapiInfoLock) {
+ gDnsapiInfoLock = new OffTheBooksMutex("GetAddrInfo.cpp::gDnsapiInfoLock");
+ }
+ OffTheBooksMutexAutoLock lock(*gDnsapiInfoLock);
+
+ if (gDnsapiInfo) {
+ MOZ_ASSERT_UNREACHABLE("GetAddrInfo is being initialized multiple times!");
+ return NS_ERROR_ALREADY_INITIALIZED;
+ }
+
+ HMODULE library = LoadLibraryA("Dnsapi.dll");
+ if (NS_WARN_IF(!library)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ FARPROC dnsQueryFunc = GetProcAddress(library, "DnsQuery_A");
+ FARPROC dnsFreeFunc = GetProcAddress(library, "DnsFree");
+ if (NS_WARN_IF(!dnsQueryFunc) || NS_WARN_IF(!dnsFreeFunc)) {
+ DebugOnly<BOOL> rv = FreeLibrary(library);
+ NS_WARNING_ASSERTION(rv, "Failed to free Dnsapi.dll.");
+ return NS_ERROR_FAILURE;
+ }
+
+ DnsapiInfo* info = new DnsapiInfo;
+ info->mLibrary = library;
+ info->mDnsQueryFunc = (decltype(info->mDnsQueryFunc)) dnsQueryFunc;
+ info->mDnsFreeFunc = (decltype(info->mDnsFreeFunc)) dnsFreeFunc;
+ gDnsapiInfo = info;
+
+ return NS_OK;
+}
+
+static MOZ_ALWAYS_INLINE nsresult
+_GetAddrInfoShutdown_Windows()
+{
+ OffTheBooksMutexAutoLock lock(*gDnsapiInfoLock);
+
+ if (NS_WARN_IF(!gDnsapiInfo) || NS_WARN_IF(!gDnsapiInfoLock)) {
+ MOZ_ASSERT_UNREACHABLE("GetAddrInfo not initialized!");
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ gDnsapiInfo = nullptr;
+
+ return NS_OK;
+}
+
+// If successful, returns in aResult a TTL value that is smaller or
+// equal with the one already there. Gets the TTL value by calling
+// to dnsapi->mDnsQueryFunc and iterating through the returned
+// records to find the one with the smallest TTL value.
+static MOZ_ALWAYS_INLINE nsresult
+_GetMinTTLForRequestType_Windows(DnsapiInfo * dnsapi, const char* aHost,
+ uint16_t aRequestType, unsigned int* aResult)
+{
+ MOZ_ASSERT(dnsapi);
+ MOZ_ASSERT(aHost);
+ MOZ_ASSERT(aResult);
+
+ PDNS_RECORDA dnsData = nullptr;
+ DNS_STATUS status = dnsapi->mDnsQueryFunc(
+ aHost,
+ aRequestType,
+ (DNS_QUERY_STANDARD | DNS_QUERY_NO_NETBT | DNS_QUERY_NO_HOSTS_FILE
+ | DNS_QUERY_NO_MULTICAST | DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE
+ | DNS_QUERY_DONT_RESET_TTL_VALUES),
+ nullptr,
+ &dnsData,
+ nullptr);
+ if (status == DNS_INFO_NO_RECORDS || status == DNS_ERROR_RCODE_NAME_ERROR
+ || !dnsData) {
+ LOG("No DNS records found for %s. status=%X. aRequestType = %X\n",
+ aHost, status, aRequestType);
+ return NS_ERROR_FAILURE;
+ } else if (status != NOERROR) {
+ LOG_WARNING("DnsQuery_A failed with status %X.\n", status);
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ for (PDNS_RECORDA curRecord = dnsData; curRecord; curRecord = curRecord->pNext) {
+ // Only records in the answer section are important
+ if (curRecord->Flags.S.Section != DnsSectionAnswer) {
+ continue;
+ }
+
+ if (curRecord->wType == aRequestType) {
+ *aResult = std::min<unsigned int>(*aResult, curRecord->dwTtl);
+ } else {
+ LOG("Received unexpected record type %u in response for %s.\n",
+ curRecord->wType, aHost);
+ }
+ }
+
+ dnsapi->mDnsFreeFunc(dnsData, DNS_FREE_TYPE::DnsFreeRecordList);
+ return NS_OK;
+}
+
+static MOZ_ALWAYS_INLINE nsresult
+_GetTTLData_Windows(const char* aHost, uint16_t* aResult, uint16_t aAddressFamily)
+{
+ MOZ_ASSERT(aHost);
+ MOZ_ASSERT(aResult);
+ if (aAddressFamily != PR_AF_UNSPEC &&
+ aAddressFamily != PR_AF_INET &&
+ aAddressFamily != PR_AF_INET6) {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ RefPtr<DnsapiInfo> dnsapi = nullptr;
+ {
+ OffTheBooksMutexAutoLock lock(*gDnsapiInfoLock);
+ dnsapi = gDnsapiInfo;
+ }
+
+ if (!dnsapi) {
+ LOG_WARNING("GetAddrInfo has been shutdown or has not been initialized.");
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ // In order to avoid using ANY records which are not always implemented as a
+ // "Gimme what you have" request in hostname resolvers, we should send A
+ // and/or AAAA requests, based on the address family requested.
+ unsigned int ttl = -1;
+ if (aAddressFamily == PR_AF_UNSPEC || aAddressFamily == PR_AF_INET) {
+ _GetMinTTLForRequestType_Windows(dnsapi, aHost, DNS_TYPE_A, &ttl);
+ }
+ if (aAddressFamily == PR_AF_UNSPEC || aAddressFamily == PR_AF_INET6) {
+ _GetMinTTLForRequestType_Windows(dnsapi, aHost, DNS_TYPE_AAAA, &ttl);
+ }
+
+ {
+ // dnsapi's destructor is not thread-safe, so we release explicitly here
+ OffTheBooksMutexAutoLock lock(*gDnsapiInfoLock);
+ dnsapi = nullptr;
+ }
+
+ if (ttl == -1) {
+ LOG("No useable TTL found.");
+ return NS_ERROR_FAILURE;
+ }
+
+ *aResult = ttl;
+ return NS_OK;
+}
+#endif
+
+////////////////////////////////////
+// PORTABLE RUNTIME IMPLEMENTATION//
+////////////////////////////////////
+
+static MOZ_ALWAYS_INLINE nsresult
+_GetAddrInfo_Portable(const char* aCanonHost, uint16_t aAddressFamily,
+ uint16_t aFlags, const char* aNetworkInterface,
+ AddrInfo** aAddrInfo)
+{
+ MOZ_ASSERT(aCanonHost);
+ MOZ_ASSERT(aAddrInfo);
+
+ // We accept the same aFlags that nsHostResolver::ResolveHost accepts, but we
+ // need to translate the aFlags into a form that PR_GetAddrInfoByName
+ // accepts.
+ int prFlags = PR_AI_ADDRCONFIG;
+ if (!(aFlags & nsHostResolver::RES_CANON_NAME)) {
+ prFlags |= PR_AI_NOCANONNAME;
+ }
+
+ // We need to remove IPv4 records manually because PR_GetAddrInfoByName
+ // doesn't support PR_AF_INET6.
+ bool disableIPv4 = aAddressFamily == PR_AF_INET6;
+ if (disableIPv4) {
+ aAddressFamily = PR_AF_UNSPEC;
+ }
+
+ PRAddrInfo* prai = PR_GetAddrInfoByName(aCanonHost, aAddressFamily, prFlags);
+
+ if (!prai) {
+ return NS_ERROR_UNKNOWN_HOST;
+ }
+
+ const char* canonName = nullptr;
+ if (aFlags & nsHostResolver::RES_CANON_NAME) {
+ canonName = PR_GetCanonNameFromAddrInfo(prai);
+ }
+
+ bool filterNameCollision = !(aFlags & nsHostResolver::RES_ALLOW_NAME_COLLISION);
+ nsAutoPtr<AddrInfo> ai(new AddrInfo(aCanonHost, prai, disableIPv4,
+ filterNameCollision, canonName));
+ PR_FreeAddrInfo(prai);
+ if (ai->mAddresses.isEmpty()) {
+ return NS_ERROR_UNKNOWN_HOST;
+ }
+
+ *aAddrInfo = ai.forget();
+
+ return NS_OK;
+}
+
+//////////////////////////////////////
+// COMMON/PLATFORM INDEPENDENT CODE //
+//////////////////////////////////////
+nsresult
+GetAddrInfoInit() {
+ LOG("Initializing GetAddrInfo.\n");
+
+#if DNSQUERY_AVAILABLE
+ return _GetAddrInfoInit_Windows();
+#else
+ return NS_OK;
+#endif
+}
+
+nsresult
+GetAddrInfoShutdown() {
+ LOG("Shutting down GetAddrInfo.\n");
+
+#if DNSQUERY_AVAILABLE
+ return _GetAddrInfoShutdown_Windows();
+#else
+ return NS_OK;
+#endif
+}
+
+nsresult
+GetAddrInfo(const char* aHost, uint16_t aAddressFamily, uint16_t aFlags,
+ const char* aNetworkInterface, AddrInfo** aAddrInfo, bool aGetTtl)
+{
+ if (NS_WARN_IF(!aHost) || NS_WARN_IF(!aAddrInfo)) {
+ return NS_ERROR_NULL_POINTER;
+ }
+
+#if DNSQUERY_AVAILABLE
+ // The GetTTLData needs the canonical name to function properly
+ if (aGetTtl) {
+ aFlags |= nsHostResolver::RES_CANON_NAME;
+ }
+#endif
+
+ *aAddrInfo = nullptr;
+ nsresult rv = _GetAddrInfo_Portable(aHost, aAddressFamily, aFlags,
+ aNetworkInterface, aAddrInfo);
+
+#if DNSQUERY_AVAILABLE
+ if (aGetTtl && NS_SUCCEEDED(rv)) {
+ // Figure out the canonical name, or if that fails, just use the host name
+ // we have.
+ const char *name = nullptr;
+ if (*aAddrInfo != nullptr && (*aAddrInfo)->mCanonicalName) {
+ name = (*aAddrInfo)->mCanonicalName;
+ } else {
+ name = aHost;
+ }
+
+ LOG("Getting TTL for %s (cname = %s).", aHost, name);
+ uint16_t ttl = 0;
+ nsresult ttlRv = _GetTTLData_Windows(name, &ttl, aAddressFamily);
+ if (NS_SUCCEEDED(ttlRv)) {
+ (*aAddrInfo)->ttl = ttl;
+ LOG("Got TTL %u for %s (name = %s).", ttl, aHost, name);
+ } else {
+ LOG_WARNING("Could not get TTL for %s (cname = %s).", aHost, name);
+ }
+ }
+#endif
+
+ return rv;
+}
+
+} // namespace net
+} // namespace mozilla
diff --git a/netwerk/dns/GetAddrInfo.h b/netwerk/dns/GetAddrInfo.h
new file mode 100644
index 000000000..57c008dd5
--- /dev/null
+++ b/netwerk/dns/GetAddrInfo.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef netwerk_dns_GetAddrInfo_h
+#define netwerk_dns_GetAddrInfo_h
+
+#include "nsError.h"
+#include "nscore.h"
+
+#if defined(XP_WIN)
+#define DNSQUERY_AVAILABLE 1
+#define TTL_AVAILABLE 1
+#else
+#define DNSQUERY_AVAILABLE 0
+#define TTL_AVAILABLE 0
+#endif
+
+namespace mozilla {
+namespace net {
+
+class AddrInfo;
+
+/**
+ * Look up a host by name. Mostly equivalent to getaddrinfo(host, NULL, ...) of
+ * RFC 3493.
+ *
+ * @param aHost[in] Character string defining the host name of interest
+ * @param aAddressFamily[in] May be AF_INET, AF_INET6, or AF_UNSPEC.
+ * @param aFlags[in] May be either PR_AI_ADDRCONFIG or
+ * PR_AI_ADDRCONFIG | PR_AI_NOCANONNAME. Include PR_AI_NOCANONNAME to
+ * suppress the determination of the canonical name corresponding to
+ * hostname (PR_AI_NOCANONNAME will be ignored if the TTL is retrieved).
+ * @param aAddrInfo[out] Will point to the results of the host lookup, or be
+ * null if the lookup failed.
+ * @param aGetTtl[in] If true, and TTL_AVAILABLE is truthy, the TTL will be
+ * retrieved if DNS provides the answers..
+ */
+nsresult
+GetAddrInfo(const char* aHost, uint16_t aAddressFamily, uint16_t aFlags,
+ const char* aNetworkInterface, AddrInfo** aAddrInfo, bool aGetTtl);
+
+/**
+ * Initialize the GetAddrInfo module.
+ *
+ * GetAddrInfoShutdown() should be called for every time this function is
+ * called.
+ */
+nsresult
+GetAddrInfoInit();
+
+/**
+ * Shutdown the GetAddrInfo module.
+ *
+ * This function should be called for every time GetAddrInfoInit() is called.
+ * An assertion may throw (but is not guarenteed) if this function is called
+ * too many times.
+ */
+nsresult
+GetAddrInfoShutdown();
+
+} // namespace net
+} // namespace mozilla
+
+#endif // netwerk_dns_GetAddrInfo_h
diff --git a/netwerk/dns/PDNSParams.h b/netwerk/dns/PDNSParams.h
new file mode 100644
index 000000000..e5e668164
--- /dev/null
+++ b/netwerk/dns/PDNSParams.h
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=c: */
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef PDNSParams_h
+#define PDNSParams_h
+
+#include "DNS.h"
+#include "nsTArray.h"
+
+namespace mozilla {
+namespace net {
+
+// Need to define typedef in .h file--can't seem to in ipdl.h file?
+typedef nsTArray<NetAddr> NetAddrArray;
+
+} // namespace net
+} // namespace mozilla
+
+#endif // PDNSParams_h
diff --git a/netwerk/dns/PDNSRequest.ipdl b/netwerk/dns/PDNSRequest.ipdl
new file mode 100644
index 000000000..2288ab09e
--- /dev/null
+++ b/netwerk/dns/PDNSRequest.ipdl
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+include protocol PNecko;
+
+include PDNSRequestParams;
+
+include "mozilla/net/NeckoMessageUtils.h";
+
+namespace mozilla {
+namespace net {
+
+async protocol PDNSRequest
+{
+ manager PNecko;
+
+parent:
+ // constructor in PNecko takes AsyncResolve args that initialize request
+
+ // Pass args here rather than storing them in the parent; they are only
+ // needed if the request is to be canceled.
+ async CancelDNSRequest(nsCString hostName, uint32_t flags,
+ nsCString networkInterface, nsresult reason);
+ async __delete__();
+
+child:
+ async LookupCompleted(DNSRequestResponse reply);
+
+};
+
+} //namespace net
+} //namespace mozilla
diff --git a/netwerk/dns/PDNSRequestParams.ipdlh b/netwerk/dns/PDNSRequestParams.ipdlh
new file mode 100644
index 000000000..d06f27cfa
--- /dev/null
+++ b/netwerk/dns/PDNSRequestParams.ipdlh
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+using NetAddrArray from "mozilla/net/PDNSParams.h";
+
+namespace mozilla {
+namespace net {
+
+//-----------------------------------------------------------------------------
+// DNS IPDL structs
+//-----------------------------------------------------------------------------
+
+struct DNSRecord
+{
+ nsCString canonicalName;
+ NetAddrArray addrs;
+};
+
+union DNSRequestResponse
+{
+ DNSRecord;
+ nsresult; // if error
+};
+
+
+} // namespace ipc
+} // namespace mozilla
diff --git a/netwerk/dns/effective_tld_names.dat b/netwerk/dns/effective_tld_names.dat
new file mode 100644
index 000000000..24165a090
--- /dev/null
+++ b/netwerk/dns/effective_tld_names.dat
@@ -0,0 +1,10834 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+// ===BEGIN ICANN DOMAINS===
+
+// ac : http://en.wikipedia.org/wiki/.ac
+ac
+com.ac
+edu.ac
+gov.ac
+net.ac
+mil.ac
+org.ac
+
+// ad : http://en.wikipedia.org/wiki/.ad
+ad
+nom.ad
+
+// ae : http://en.wikipedia.org/wiki/.ae
+// see also: "Domain Name Eligibility Policy" at http://www.aeda.ae/eng/aepolicy.php
+ae
+co.ae
+net.ae
+org.ae
+sch.ae
+ac.ae
+gov.ae
+mil.ae
+
+// aero : see http://www.information.aero/index.php?id=66
+aero
+accident-investigation.aero
+accident-prevention.aero
+aerobatic.aero
+aeroclub.aero
+aerodrome.aero
+agents.aero
+aircraft.aero
+airline.aero
+airport.aero
+air-surveillance.aero
+airtraffic.aero
+air-traffic-control.aero
+ambulance.aero
+amusement.aero
+association.aero
+author.aero
+ballooning.aero
+broker.aero
+caa.aero
+cargo.aero
+catering.aero
+certification.aero
+championship.aero
+charter.aero
+civilaviation.aero
+club.aero
+conference.aero
+consultant.aero
+consulting.aero
+control.aero
+council.aero
+crew.aero
+design.aero
+dgca.aero
+educator.aero
+emergency.aero
+engine.aero
+engineer.aero
+entertainment.aero
+equipment.aero
+exchange.aero
+express.aero
+federation.aero
+flight.aero
+freight.aero
+fuel.aero
+gliding.aero
+government.aero
+groundhandling.aero
+group.aero
+hanggliding.aero
+homebuilt.aero
+insurance.aero
+journal.aero
+journalist.aero
+leasing.aero
+logistics.aero
+magazine.aero
+maintenance.aero
+marketplace.aero
+media.aero
+microlight.aero
+modelling.aero
+navigation.aero
+parachuting.aero
+paragliding.aero
+passenger-association.aero
+pilot.aero
+press.aero
+production.aero
+recreation.aero
+repbody.aero
+res.aero
+research.aero
+rotorcraft.aero
+safety.aero
+scientist.aero
+services.aero
+show.aero
+skydiving.aero
+software.aero
+student.aero
+taxi.aero
+trader.aero
+trading.aero
+trainer.aero
+union.aero
+workinggroup.aero
+works.aero
+
+// af : http://www.nic.af/help.jsp
+af
+gov.af
+com.af
+org.af
+net.af
+edu.af
+
+// ag : http://www.nic.ag/prices.htm
+ag
+com.ag
+org.ag
+net.ag
+co.ag
+nom.ag
+
+// ai : http://nic.com.ai/
+ai
+off.ai
+com.ai
+net.ai
+org.ai
+
+// al : http://www.ert.gov.al/ert_alb/faq_det.html?Id=31
+al
+com.al
+edu.al
+gov.al
+mil.al
+net.al
+org.al
+
+// am : http://en.wikipedia.org/wiki/.am
+am
+
+// an : http://www.una.an/an_domreg/default.asp
+an
+com.an
+net.an
+org.an
+edu.an
+
+// ao : http://en.wikipedia.org/wiki/.ao
+// http://www.dns.ao/REGISTR.DOC
+ao
+ed.ao
+gv.ao
+og.ao
+co.ao
+pb.ao
+it.ao
+
+// aq : http://en.wikipedia.org/wiki/.aq
+aq
+
+// ar : https://nic.ar/normativa-vigente.xhtml
+ar
+com.ar
+edu.ar
+gob.ar
+gov.ar
+int.ar
+mil.ar
+net.ar
+org.ar
+tur.ar
+
+// arpa : http://en.wikipedia.org/wiki/.arpa
+// Confirmed by registry <iana-questions@icann.org> 2008-06-18
+arpa
+e164.arpa
+in-addr.arpa
+ip6.arpa
+iris.arpa
+uri.arpa
+urn.arpa
+
+// as : http://en.wikipedia.org/wiki/.as
+as
+gov.as
+
+// asia : http://en.wikipedia.org/wiki/.asia
+asia
+
+// at : http://en.wikipedia.org/wiki/.at
+// Confirmed by registry <it@nic.at> 2008-06-17
+at
+ac.at
+co.at
+gv.at
+or.at
+
+// au : http://en.wikipedia.org/wiki/.au
+// http://www.auda.org.au/
+au
+// 2LDs
+com.au
+net.au
+org.au
+edu.au
+gov.au
+asn.au
+id.au
+// Historic 2LDs (closed to new registration, but sites still exist)
+info.au
+conf.au
+oz.au
+// CGDNs - http://www.cgdn.org.au/
+act.au
+nsw.au
+nt.au
+qld.au
+sa.au
+tas.au
+vic.au
+wa.au
+// 3LDs
+act.edu.au
+nsw.edu.au
+nt.edu.au
+qld.edu.au
+sa.edu.au
+tas.edu.au
+vic.edu.au
+wa.edu.au
+// act.gov.au Bug 984824 - Removed at request of Greg Tankard
+// nsw.gov.au Bug 547985 - Removed at request of <Shae.Donelan@services.nsw.gov.au>
+// nt.gov.au Bug 940478 - Removed at request of Greg Connors <Greg.Connors@nt.gov.au>
+qld.gov.au
+sa.gov.au
+tas.gov.au
+vic.gov.au
+wa.gov.au
+
+// aw : http://en.wikipedia.org/wiki/.aw
+aw
+com.aw
+
+// ax : http://en.wikipedia.org/wiki/.ax
+ax
+
+// az : http://en.wikipedia.org/wiki/.az
+az
+com.az
+net.az
+int.az
+gov.az
+org.az
+edu.az
+info.az
+pp.az
+mil.az
+name.az
+pro.az
+biz.az
+
+// ba : http://en.wikipedia.org/wiki/.ba
+ba
+org.ba
+net.ba
+edu.ba
+gov.ba
+mil.ba
+unsa.ba
+unbi.ba
+co.ba
+com.ba
+rs.ba
+
+// bb : http://en.wikipedia.org/wiki/.bb
+bb
+biz.bb
+co.bb
+com.bb
+edu.bb
+gov.bb
+info.bb
+net.bb
+org.bb
+store.bb
+tv.bb
+
+// bd : http://en.wikipedia.org/wiki/.bd
+*.bd
+
+// be : http://en.wikipedia.org/wiki/.be
+// Confirmed by registry <tech@dns.be> 2008-06-08
+be
+ac.be
+
+// bf : http://en.wikipedia.org/wiki/.bf
+bf
+gov.bf
+
+// bg : http://en.wikipedia.org/wiki/.bg
+// https://www.register.bg/user/static/rules/en/index.html
+bg
+a.bg
+b.bg
+c.bg
+d.bg
+e.bg
+f.bg
+g.bg
+h.bg
+i.bg
+j.bg
+k.bg
+l.bg
+m.bg
+n.bg
+o.bg
+p.bg
+q.bg
+r.bg
+s.bg
+t.bg
+u.bg
+v.bg
+w.bg
+x.bg
+y.bg
+z.bg
+0.bg
+1.bg
+2.bg
+3.bg
+4.bg
+5.bg
+6.bg
+7.bg
+8.bg
+9.bg
+
+// bh : http://en.wikipedia.org/wiki/.bh
+bh
+com.bh
+edu.bh
+net.bh
+org.bh
+gov.bh
+
+// bi : http://en.wikipedia.org/wiki/.bi
+// http://whois.nic.bi/
+bi
+co.bi
+com.bi
+edu.bi
+or.bi
+org.bi
+
+// biz : http://en.wikipedia.org/wiki/.biz
+biz
+
+// bj : http://en.wikipedia.org/wiki/.bj
+bj
+asso.bj
+barreau.bj
+gouv.bj
+
+// bm : http://www.bermudanic.bm/dnr-text.txt
+bm
+com.bm
+edu.bm
+gov.bm
+net.bm
+org.bm
+
+// bn : http://en.wikipedia.org/wiki/.bn
+*.bn
+
+// bo : http://www.nic.bo/
+bo
+com.bo
+edu.bo
+gov.bo
+gob.bo
+int.bo
+org.bo
+net.bo
+mil.bo
+tv.bo
+
+// br : http://registro.br/dominio/categoria.html
+// Submitted by registry <fneves@registro.br> 2014-08-11
+br
+adm.br
+adv.br
+agr.br
+am.br
+arq.br
+art.br
+ato.br
+b.br
+bio.br
+blog.br
+bmd.br
+cim.br
+cng.br
+cnt.br
+com.br
+coop.br
+ecn.br
+eco.br
+edu.br
+emp.br
+eng.br
+esp.br
+etc.br
+eti.br
+far.br
+flog.br
+fm.br
+fnd.br
+fot.br
+fst.br
+g12.br
+ggf.br
+gov.br
+imb.br
+ind.br
+inf.br
+jor.br
+jus.br
+leg.br
+lel.br
+mat.br
+med.br
+mil.br
+mp.br
+mus.br
+net.br
+*.nom.br
+not.br
+ntr.br
+odo.br
+org.br
+ppg.br
+pro.br
+psc.br
+psi.br
+qsl.br
+radio.br
+rec.br
+slg.br
+srv.br
+taxi.br
+teo.br
+tmp.br
+trd.br
+tur.br
+tv.br
+vet.br
+vlog.br
+wiki.br
+zlg.br
+
+// bs : http://www.nic.bs/rules.html
+bs
+com.bs
+net.bs
+org.bs
+edu.bs
+gov.bs
+
+// bt : http://en.wikipedia.org/wiki/.bt
+bt
+com.bt
+edu.bt
+gov.bt
+net.bt
+org.bt
+
+// bv : No registrations at this time.
+// Submitted by registry <jarle@uninett.no> 2006-06-16
+bv
+
+// bw : http://en.wikipedia.org/wiki/.bw
+// http://www.gobin.info/domainname/bw.doc
+// list of other 2nd level tlds ?
+bw
+co.bw
+org.bw
+
+// by : http://en.wikipedia.org/wiki/.by
+// http://tld.by/rules_2006_en.html
+// list of other 2nd level tlds ?
+by
+gov.by
+mil.by
+// Official information does not indicate that com.by is a reserved
+// second-level domain, but it's being used as one (see www.google.com.by and
+// www.yahoo.com.by, for example), so we list it here for safety's sake.
+com.by
+
+// http://hoster.by/
+of.by
+
+// bz : http://en.wikipedia.org/wiki/.bz
+// http://www.belizenic.bz/
+bz
+com.bz
+net.bz
+org.bz
+edu.bz
+gov.bz
+
+// ca : http://en.wikipedia.org/wiki/.ca
+ca
+// ca geographical names
+ab.ca
+bc.ca
+mb.ca
+nb.ca
+nf.ca
+nl.ca
+ns.ca
+nt.ca
+nu.ca
+on.ca
+pe.ca
+qc.ca
+sk.ca
+yk.ca
+// gc.ca: http://en.wikipedia.org/wiki/.gc.ca
+// see also: http://registry.gc.ca/en/SubdomainFAQ
+gc.ca
+
+// cat : http://en.wikipedia.org/wiki/.cat
+cat
+
+// cc : http://en.wikipedia.org/wiki/.cc
+cc
+
+// cd : http://en.wikipedia.org/wiki/.cd
+// see also: https://www.nic.cd/domain/insertDomain_2.jsp?act=1
+cd
+gov.cd
+
+// cf : http://en.wikipedia.org/wiki/.cf
+cf
+
+// cg : http://en.wikipedia.org/wiki/.cg
+cg
+
+// ch : http://en.wikipedia.org/wiki/.ch
+ch
+
+// ci : http://en.wikipedia.org/wiki/.ci
+// http://www.nic.ci/index.php?page=charte
+ci
+org.ci
+or.ci
+com.ci
+co.ci
+edu.ci
+ed.ci
+ac.ci
+net.ci
+go.ci
+asso.ci
+aéroport.ci
+int.ci
+presse.ci
+md.ci
+gouv.ci
+
+// ck : http://en.wikipedia.org/wiki/.ck
+*.ck
+!www.ck
+
+// cl : http://en.wikipedia.org/wiki/.cl
+cl
+gov.cl
+gob.cl
+co.cl
+mil.cl
+
+// cm : http://en.wikipedia.org/wiki/.cm plus bug 981927
+cm
+co.cm
+com.cm
+gov.cm
+net.cm
+
+// cn : http://en.wikipedia.org/wiki/.cn
+// Submitted by registry <tanyaling@cnnic.cn> 2008-06-11
+cn
+ac.cn
+com.cn
+edu.cn
+gov.cn
+net.cn
+org.cn
+mil.cn
+公司.cn
+网络.cn
+網絡.cn
+// cn geographic names
+ah.cn
+bj.cn
+cq.cn
+fj.cn
+gd.cn
+gs.cn
+gz.cn
+gx.cn
+ha.cn
+hb.cn
+he.cn
+hi.cn
+hl.cn
+hn.cn
+jl.cn
+js.cn
+jx.cn
+ln.cn
+nm.cn
+nx.cn
+qh.cn
+sc.cn
+sd.cn
+sh.cn
+sn.cn
+sx.cn
+tj.cn
+xj.cn
+xz.cn
+yn.cn
+zj.cn
+hk.cn
+mo.cn
+tw.cn
+
+// co : http://en.wikipedia.org/wiki/.co
+// Submitted by registry <tecnico@uniandes.edu.co> 2008-06-11
+co
+arts.co
+com.co
+edu.co
+firm.co
+gov.co
+info.co
+int.co
+mil.co
+net.co
+nom.co
+org.co
+rec.co
+web.co
+
+// com : http://en.wikipedia.org/wiki/.com
+com
+
+// coop : http://en.wikipedia.org/wiki/.coop
+coop
+
+// cr : http://www.nic.cr/niccr_publico/showRegistroDominiosScreen.do
+cr
+ac.cr
+co.cr
+ed.cr
+fi.cr
+go.cr
+or.cr
+sa.cr
+
+// cu : http://en.wikipedia.org/wiki/.cu
+cu
+com.cu
+edu.cu
+org.cu
+net.cu
+gov.cu
+inf.cu
+
+// cv : http://en.wikipedia.org/wiki/.cv
+cv
+
+// cw : http://www.una.cw/cw_registry/
+// Confirmed by registry <registry@una.net> 2013-03-26
+cw
+com.cw
+edu.cw
+net.cw
+org.cw
+
+// cx : http://en.wikipedia.org/wiki/.cx
+// list of other 2nd level tlds ?
+cx
+gov.cx
+
+// cy : http://en.wikipedia.org/wiki/.cy
+ac.cy
+biz.cy
+com.cy
+ekloges.cy
+gov.cy
+ltd.cy
+name.cy
+net.cy
+org.cy
+parliament.cy
+press.cy
+pro.cy
+tm.cy
+
+// cz : http://en.wikipedia.org/wiki/.cz
+cz
+
+// de : http://en.wikipedia.org/wiki/.de
+// Confirmed by registry <ops@denic.de> (with technical
+// reservations) 2008-07-01
+de
+
+// dj : http://en.wikipedia.org/wiki/.dj
+dj
+
+// dk : http://en.wikipedia.org/wiki/.dk
+// Confirmed by registry <robert@dk-hostmaster.dk> 2008-06-17
+dk
+
+// dm : http://en.wikipedia.org/wiki/.dm
+dm
+com.dm
+net.dm
+org.dm
+edu.dm
+gov.dm
+
+// do : http://en.wikipedia.org/wiki/.do
+do
+art.do
+com.do
+edu.do
+gob.do
+gov.do
+mil.do
+net.do
+org.do
+sld.do
+web.do
+
+// dz : http://en.wikipedia.org/wiki/.dz
+dz
+com.dz
+org.dz
+net.dz
+gov.dz
+edu.dz
+asso.dz
+pol.dz
+art.dz
+
+// ec : http://www.nic.ec/reg/paso1.asp
+// Submitted by registry <vabboud@nic.ec> 2008-07-04
+ec
+com.ec
+info.ec
+net.ec
+fin.ec
+k12.ec
+med.ec
+pro.ec
+org.ec
+edu.ec
+gov.ec
+gob.ec
+mil.ec
+
+// edu : http://en.wikipedia.org/wiki/.edu
+edu
+
+// ee : http://www.eenet.ee/EENet/dom_reeglid.html#lisa_B
+ee
+edu.ee
+gov.ee
+riik.ee
+lib.ee
+med.ee
+com.ee
+pri.ee
+aip.ee
+org.ee
+fie.ee
+
+// eg : http://en.wikipedia.org/wiki/.eg
+eg
+com.eg
+edu.eg
+eun.eg
+gov.eg
+mil.eg
+name.eg
+net.eg
+org.eg
+sci.eg
+
+// er : http://en.wikipedia.org/wiki/.er
+*.er
+
+// es : https://www.nic.es/site_ingles/ingles/dominios/index.html
+es
+com.es
+nom.es
+org.es
+gob.es
+edu.es
+
+// et : http://en.wikipedia.org/wiki/.et
+et
+com.et
+gov.et
+org.et
+edu.et
+biz.et
+name.et
+info.et
+net.et
+
+// eu : http://en.wikipedia.org/wiki/.eu
+eu
+
+// fi : http://en.wikipedia.org/wiki/.fi
+fi
+// aland.fi : http://en.wikipedia.org/wiki/.ax
+// This domain is being phased out in favor of .ax. As there are still many
+// domains under aland.fi, we still keep it on the list until aland.fi is
+// completely removed.
+// TODO: Check for updates (expected to be phased out around Q1/2009)
+aland.fi
+
+// fj : http://en.wikipedia.org/wiki/.fj
+*.fj
+
+// fk : http://en.wikipedia.org/wiki/.fk
+*.fk
+
+// fm : http://en.wikipedia.org/wiki/.fm
+fm
+
+// fo : http://en.wikipedia.org/wiki/.fo
+fo
+
+// fr : http://www.afnic.fr/
+// domaines descriptifs : http://www.afnic.fr/obtenir/chartes/nommage-fr/annexe-descriptifs
+fr
+com.fr
+asso.fr
+nom.fr
+prd.fr
+presse.fr
+tm.fr
+// domaines sectoriels : http://www.afnic.fr/obtenir/chartes/nommage-fr/annexe-sectoriels
+aeroport.fr
+assedic.fr
+avocat.fr
+avoues.fr
+cci.fr
+chambagri.fr
+chirurgiens-dentistes.fr
+experts-comptables.fr
+geometre-expert.fr
+gouv.fr
+greta.fr
+huissier-justice.fr
+medecin.fr
+notaires.fr
+pharmacien.fr
+port.fr
+veterinaire.fr
+
+// ga : http://en.wikipedia.org/wiki/.ga
+ga
+
+// gb : This registry is effectively dormant
+// Submitted by registry <Damien.Shaw@ja.net> 2008-06-12
+gb
+
+// gd : http://en.wikipedia.org/wiki/.gd
+gd
+
+// ge : http://www.nic.net.ge/policy_en.pdf
+ge
+com.ge
+edu.ge
+gov.ge
+org.ge
+mil.ge
+net.ge
+pvt.ge
+
+// gf : http://en.wikipedia.org/wiki/.gf
+gf
+
+// gg : http://www.channelisles.net/register-domains/
+// Confirmed by registry <nigel@channelisles.net> 2013-11-28
+gg
+co.gg
+net.gg
+org.gg
+
+// gh : http://en.wikipedia.org/wiki/.gh
+// see also: http://www.nic.gh/reg_now.php
+// Although domains directly at second level are not possible at the moment,
+// they have been possible for some time and may come back.
+gh
+com.gh
+edu.gh
+gov.gh
+org.gh
+mil.gh
+
+// gi : http://www.nic.gi/rules.html
+gi
+com.gi
+ltd.gi
+gov.gi
+mod.gi
+edu.gi
+org.gi
+
+// gl : http://en.wikipedia.org/wiki/.gl
+// http://nic.gl
+gl
+co.gl
+com.gl
+edu.gl
+net.gl
+org.gl
+
+// gm : http://www.nic.gm/htmlpages%5Cgm-policy.htm
+gm
+
+// gn : http://psg.com/dns/gn/gn.txt
+// Submitted by registry <randy@psg.com> 2008-06-17
+gn
+ac.gn
+com.gn
+edu.gn
+gov.gn
+org.gn
+net.gn
+
+// gov : http://en.wikipedia.org/wiki/.gov
+gov
+
+// gp : http://www.nic.gp/index.php?lang=en
+gp
+com.gp
+net.gp
+mobi.gp
+edu.gp
+org.gp
+asso.gp
+
+// gq : http://en.wikipedia.org/wiki/.gq
+gq
+
+// gr : https://grweb.ics.forth.gr/english/1617-B-2005.html
+// Submitted by registry <segred@ics.forth.gr> 2008-06-09
+gr
+com.gr
+edu.gr
+net.gr
+org.gr
+gov.gr
+
+// gs : http://en.wikipedia.org/wiki/.gs
+gs
+
+// gt : http://www.gt/politicas_de_registro.html
+gt
+com.gt
+edu.gt
+gob.gt
+ind.gt
+mil.gt
+net.gt
+org.gt
+
+// gu : http://gadao.gov.gu/registration.txt
+*.gu
+
+// gw : http://en.wikipedia.org/wiki/.gw
+gw
+
+// gy : http://en.wikipedia.org/wiki/.gy
+// http://registry.gy/
+gy
+co.gy
+com.gy
+net.gy
+
+// hk : https://www.hkdnr.hk
+// Submitted by registry <hk.tech@hkirc.hk> 2008-06-11
+hk
+com.hk
+edu.hk
+gov.hk
+idv.hk
+net.hk
+org.hk
+公司.hk
+教育.hk
+敎育.hk
+政府.hk
+個人.hk
+个人.hk
+箇人.hk
+網络.hk
+网络.hk
+组織.hk
+網絡.hk
+网絡.hk
+组织.hk
+組織.hk
+組织.hk
+
+// hm : http://en.wikipedia.org/wiki/.hm
+hm
+
+// hn : http://www.nic.hn/politicas/ps02,,05.html
+hn
+com.hn
+edu.hn
+org.hn
+net.hn
+mil.hn
+gob.hn
+
+// hr : http://www.dns.hr/documents/pdf/HRTLD-regulations.pdf
+hr
+iz.hr
+from.hr
+name.hr
+com.hr
+
+// ht : http://www.nic.ht/info/charte.cfm
+ht
+com.ht
+shop.ht
+firm.ht
+info.ht
+adult.ht
+net.ht
+pro.ht
+org.ht
+med.ht
+art.ht
+coop.ht
+pol.ht
+asso.ht
+edu.ht
+rel.ht
+gouv.ht
+perso.ht
+
+// hu : http://www.domain.hu/domain/English/sld.html
+// Confirmed by registry <pasztor@iszt.hu> 2008-06-12
+hu
+co.hu
+info.hu
+org.hu
+priv.hu
+sport.hu
+tm.hu
+2000.hu
+agrar.hu
+bolt.hu
+casino.hu
+city.hu
+erotica.hu
+erotika.hu
+film.hu
+forum.hu
+games.hu
+hotel.hu
+ingatlan.hu
+jogasz.hu
+konyvelo.hu
+lakas.hu
+media.hu
+news.hu
+reklam.hu
+sex.hu
+shop.hu
+suli.hu
+szex.hu
+tozsde.hu
+utazas.hu
+video.hu
+
+// id : https://register.pandi.or.id/
+id
+ac.id
+biz.id
+co.id
+desa.id
+go.id
+mil.id
+my.id
+net.id
+or.id
+sch.id
+web.id
+
+// ie : http://en.wikipedia.org/wiki/.ie
+ie
+gov.ie
+
+// il : http://en.wikipedia.org/wiki/.il
+*.il
+
+// im : https://www.nic.im/
+// Submitted by registry <info@nic.im> 2013-11-15
+im
+ac.im
+co.im
+com.im
+ltd.co.im
+net.im
+org.im
+plc.co.im
+tt.im
+tv.im
+
+// in : http://en.wikipedia.org/wiki/.in
+// see also: https://registry.in/Policies
+// Please note, that nic.in is not an offical eTLD, but used by most
+// government institutions.
+in
+co.in
+firm.in
+net.in
+org.in
+gen.in
+ind.in
+nic.in
+ac.in
+edu.in
+res.in
+gov.in
+mil.in
+
+// info : http://en.wikipedia.org/wiki/.info
+info
+
+// int : http://en.wikipedia.org/wiki/.int
+// Confirmed by registry <iana-questions@icann.org> 2008-06-18
+int
+eu.int
+
+// io : http://www.nic.io/rules.html
+// list of other 2nd level tlds ?
+io
+com.io
+
+// iq : http://www.cmc.iq/english/iq/iqregister1.htm
+iq
+gov.iq
+edu.iq
+mil.iq
+com.iq
+org.iq
+net.iq
+
+// ir : http://www.nic.ir/Terms_and_Conditions_ir,_Appendix_1_Domain_Rules
+// Also see http://www.nic.ir/Internationalized_Domain_Names
+// Two <iran>.ir entries added at request of <tech-team@nic.ir>, 2010-04-16
+ir
+ac.ir
+co.ir
+gov.ir
+id.ir
+net.ir
+org.ir
+sch.ir
+// xn--mgba3a4f16a.ir (<iran>.ir, Persian YEH)
+ایران.ir
+// xn--mgba3a4fra.ir (<iran>.ir, Arabic YEH)
+ايران.ir
+
+// is : http://www.isnic.is/domain/rules.php
+// Confirmed by registry <marius@isgate.is> 2008-12-06
+is
+net.is
+com.is
+edu.is
+gov.is
+org.is
+int.is
+
+// it : http://en.wikipedia.org/wiki/.it
+it
+gov.it
+edu.it
+// Reserved geo-names:
+// http://www.nic.it/documenti/regolamenti-e-linee-guida/regolamento-assegnazione-versione-6.0.pdf
+// There is also a list of reserved geo-names corresponding to Italian municipalities
+// http://www.nic.it/documenti/appendice-c.pdf, but it is not included here.
+// Regions
+abr.it
+abruzzo.it
+aosta-valley.it
+aostavalley.it
+bas.it
+basilicata.it
+cal.it
+calabria.it
+cam.it
+campania.it
+emilia-romagna.it
+emiliaromagna.it
+emr.it
+friuli-v-giulia.it
+friuli-ve-giulia.it
+friuli-vegiulia.it
+friuli-venezia-giulia.it
+friuli-veneziagiulia.it
+friuli-vgiulia.it
+friuliv-giulia.it
+friulive-giulia.it
+friulivegiulia.it
+friulivenezia-giulia.it
+friuliveneziagiulia.it
+friulivgiulia.it
+fvg.it
+laz.it
+lazio.it
+lig.it
+liguria.it
+lom.it
+lombardia.it
+lombardy.it
+lucania.it
+mar.it
+marche.it
+mol.it
+molise.it
+piedmont.it
+piemonte.it
+pmn.it
+pug.it
+puglia.it
+sar.it
+sardegna.it
+sardinia.it
+sic.it
+sicilia.it
+sicily.it
+taa.it
+tos.it
+toscana.it
+trentino-a-adige.it
+trentino-aadige.it
+trentino-alto-adige.it
+trentino-altoadige.it
+trentino-s-tirol.it
+trentino-stirol.it
+trentino-sud-tirol.it
+trentino-sudtirol.it
+trentino-sued-tirol.it
+trentino-suedtirol.it
+trentinoa-adige.it
+trentinoaadige.it
+trentinoalto-adige.it
+trentinoaltoadige.it
+trentinos-tirol.it
+trentinostirol.it
+trentinosud-tirol.it
+trentinosudtirol.it
+trentinosued-tirol.it
+trentinosuedtirol.it
+tuscany.it
+umb.it
+umbria.it
+val-d-aosta.it
+val-daosta.it
+vald-aosta.it
+valdaosta.it
+valle-aosta.it
+valle-d-aosta.it
+valle-daosta.it
+valleaosta.it
+valled-aosta.it
+valledaosta.it
+vallee-aoste.it
+valleeaoste.it
+vao.it
+vda.it
+ven.it
+veneto.it
+// Provinces
+ag.it
+agrigento.it
+al.it
+alessandria.it
+alto-adige.it
+altoadige.it
+an.it
+ancona.it
+andria-barletta-trani.it
+andria-trani-barletta.it
+andriabarlettatrani.it
+andriatranibarletta.it
+ao.it
+aosta.it
+aoste.it
+ap.it
+aq.it
+aquila.it
+ar.it
+arezzo.it
+ascoli-piceno.it
+ascolipiceno.it
+asti.it
+at.it
+av.it
+avellino.it
+ba.it
+balsan.it
+bari.it
+barletta-trani-andria.it
+barlettatraniandria.it
+belluno.it
+benevento.it
+bergamo.it
+bg.it
+bi.it
+biella.it
+bl.it
+bn.it
+bo.it
+bologna.it
+bolzano.it
+bozen.it
+br.it
+brescia.it
+brindisi.it
+bs.it
+bt.it
+bz.it
+ca.it
+cagliari.it
+caltanissetta.it
+campidano-medio.it
+campidanomedio.it
+campobasso.it
+carbonia-iglesias.it
+carboniaiglesias.it
+carrara-massa.it
+carraramassa.it
+caserta.it
+catania.it
+catanzaro.it
+cb.it
+ce.it
+cesena-forli.it
+cesenaforli.it
+ch.it
+chieti.it
+ci.it
+cl.it
+cn.it
+co.it
+como.it
+cosenza.it
+cr.it
+cremona.it
+crotone.it
+cs.it
+ct.it
+cuneo.it
+cz.it
+dell-ogliastra.it
+dellogliastra.it
+en.it
+enna.it
+fc.it
+fe.it
+fermo.it
+ferrara.it
+fg.it
+fi.it
+firenze.it
+florence.it
+fm.it
+foggia.it
+forli-cesena.it
+forlicesena.it
+fr.it
+frosinone.it
+ge.it
+genoa.it
+genova.it
+go.it
+gorizia.it
+gr.it
+grosseto.it
+iglesias-carbonia.it
+iglesiascarbonia.it
+im.it
+imperia.it
+is.it
+isernia.it
+kr.it
+la-spezia.it
+laquila.it
+laspezia.it
+latina.it
+lc.it
+le.it
+lecce.it
+lecco.it
+li.it
+livorno.it
+lo.it
+lodi.it
+lt.it
+lu.it
+lucca.it
+macerata.it
+mantova.it
+massa-carrara.it
+massacarrara.it
+matera.it
+mb.it
+mc.it
+me.it
+medio-campidano.it
+mediocampidano.it
+messina.it
+mi.it
+milan.it
+milano.it
+mn.it
+mo.it
+modena.it
+monza-brianza.it
+monza-e-della-brianza.it
+monza.it
+monzabrianza.it
+monzaebrianza.it
+monzaedellabrianza.it
+ms.it
+mt.it
+na.it
+naples.it
+napoli.it
+no.it
+novara.it
+nu.it
+nuoro.it
+og.it
+ogliastra.it
+olbia-tempio.it
+olbiatempio.it
+or.it
+oristano.it
+ot.it
+pa.it
+padova.it
+padua.it
+palermo.it
+parma.it
+pavia.it
+pc.it
+pd.it
+pe.it
+perugia.it
+pesaro-urbino.it
+pesarourbino.it
+pescara.it
+pg.it
+pi.it
+piacenza.it
+pisa.it
+pistoia.it
+pn.it
+po.it
+pordenone.it
+potenza.it
+pr.it
+prato.it
+pt.it
+pu.it
+pv.it
+pz.it
+ra.it
+ragusa.it
+ravenna.it
+rc.it
+re.it
+reggio-calabria.it
+reggio-emilia.it
+reggiocalabria.it
+reggioemilia.it
+rg.it
+ri.it
+rieti.it
+rimini.it
+rm.it
+rn.it
+ro.it
+roma.it
+rome.it
+rovigo.it
+sa.it
+salerno.it
+sassari.it
+savona.it
+si.it
+siena.it
+siracusa.it
+so.it
+sondrio.it
+sp.it
+sr.it
+ss.it
+suedtirol.it
+sv.it
+ta.it
+taranto.it
+te.it
+tempio-olbia.it
+tempioolbia.it
+teramo.it
+terni.it
+tn.it
+to.it
+torino.it
+tp.it
+tr.it
+trani-andria-barletta.it
+trani-barletta-andria.it
+traniandriabarletta.it
+tranibarlettaandria.it
+trapani.it
+trentino.it
+trento.it
+treviso.it
+trieste.it
+ts.it
+turin.it
+tv.it
+ud.it
+udine.it
+urbino-pesaro.it
+urbinopesaro.it
+va.it
+varese.it
+vb.it
+vc.it
+ve.it
+venezia.it
+venice.it
+verbania.it
+vercelli.it
+verona.it
+vi.it
+vibo-valentia.it
+vibovalentia.it
+vicenza.it
+viterbo.it
+vr.it
+vs.it
+vt.it
+vv.it
+
+// je : http://www.channelisles.net/register-domains/
+// Confirmed by registry <nigel@channelisles.net> 2013-11-28
+je
+co.je
+net.je
+org.je
+
+// jm : http://www.com.jm/register.html
+*.jm
+
+// jo : http://www.dns.jo/Registration_policy.aspx
+jo
+com.jo
+org.jo
+net.jo
+edu.jo
+sch.jo
+gov.jo
+mil.jo
+name.jo
+
+// jobs : http://en.wikipedia.org/wiki/.jobs
+jobs
+
+// jp : http://en.wikipedia.org/wiki/.jp
+// http://jprs.co.jp/en/jpdomain.html
+// Submitted by registry <info@jprs.jp> 2014-10-30
+jp
+// jp organizational type names
+ac.jp
+ad.jp
+co.jp
+ed.jp
+go.jp
+gr.jp
+lg.jp
+ne.jp
+or.jp
+// jp prefecture type names
+aichi.jp
+akita.jp
+aomori.jp
+chiba.jp
+ehime.jp
+fukui.jp
+fukuoka.jp
+fukushima.jp
+gifu.jp
+gunma.jp
+hiroshima.jp
+hokkaido.jp
+hyogo.jp
+ibaraki.jp
+ishikawa.jp
+iwate.jp
+kagawa.jp
+kagoshima.jp
+kanagawa.jp
+kochi.jp
+kumamoto.jp
+kyoto.jp
+mie.jp
+miyagi.jp
+miyazaki.jp
+nagano.jp
+nagasaki.jp
+nara.jp
+niigata.jp
+oita.jp
+okayama.jp
+okinawa.jp
+osaka.jp
+saga.jp
+saitama.jp
+shiga.jp
+shimane.jp
+shizuoka.jp
+tochigi.jp
+tokushima.jp
+tokyo.jp
+tottori.jp
+toyama.jp
+wakayama.jp
+yamagata.jp
+yamaguchi.jp
+yamanashi.jp
+栃木.jp
+愛知.jp
+愛媛.jp
+兵庫.jp
+熊本.jp
+茨城.jp
+北海道.jp
+千葉.jp
+和歌山.jp
+長崎.jp
+長野.jp
+新潟.jp
+青森.jp
+静岡.jp
+東京.jp
+石川.jp
+埼玉.jp
+三重.jp
+京都.jp
+佐賀.jp
+大分.jp
+大阪.jp
+奈良.jp
+宮城.jp
+宮崎.jp
+富山.jp
+山口.jp
+山形.jp
+山梨.jp
+岩手.jp
+岐阜.jp
+岡山.jp
+島根.jp
+広島.jp
+徳島.jp
+沖縄.jp
+滋賀.jp
+神奈川.jp
+福井.jp
+福岡.jp
+福島.jp
+秋田.jp
+群馬.jp
+香川.jp
+高知.jp
+鳥取.jp
+鹿児島.jp
+// jp geographic type names
+// http://jprs.jp/doc/rule/saisoku-1.html
+*.kawasaki.jp
+*.kitakyushu.jp
+*.kobe.jp
+*.nagoya.jp
+*.sapporo.jp
+*.sendai.jp
+*.yokohama.jp
+!city.kawasaki.jp
+!city.kitakyushu.jp
+!city.kobe.jp
+!city.nagoya.jp
+!city.sapporo.jp
+!city.sendai.jp
+!city.yokohama.jp
+// 4th level registration
+aisai.aichi.jp
+ama.aichi.jp
+anjo.aichi.jp
+asuke.aichi.jp
+chiryu.aichi.jp
+chita.aichi.jp
+fuso.aichi.jp
+gamagori.aichi.jp
+handa.aichi.jp
+hazu.aichi.jp
+hekinan.aichi.jp
+higashiura.aichi.jp
+ichinomiya.aichi.jp
+inazawa.aichi.jp
+inuyama.aichi.jp
+isshiki.aichi.jp
+iwakura.aichi.jp
+kanie.aichi.jp
+kariya.aichi.jp
+kasugai.aichi.jp
+kira.aichi.jp
+kiyosu.aichi.jp
+komaki.aichi.jp
+konan.aichi.jp
+kota.aichi.jp
+mihama.aichi.jp
+miyoshi.aichi.jp
+nishio.aichi.jp
+nisshin.aichi.jp
+obu.aichi.jp
+oguchi.aichi.jp
+oharu.aichi.jp
+okazaki.aichi.jp
+owariasahi.aichi.jp
+seto.aichi.jp
+shikatsu.aichi.jp
+shinshiro.aichi.jp
+shitara.aichi.jp
+tahara.aichi.jp
+takahama.aichi.jp
+tobishima.aichi.jp
+toei.aichi.jp
+togo.aichi.jp
+tokai.aichi.jp
+tokoname.aichi.jp
+toyoake.aichi.jp
+toyohashi.aichi.jp
+toyokawa.aichi.jp
+toyone.aichi.jp
+toyota.aichi.jp
+tsushima.aichi.jp
+yatomi.aichi.jp
+akita.akita.jp
+daisen.akita.jp
+fujisato.akita.jp
+gojome.akita.jp
+hachirogata.akita.jp
+happou.akita.jp
+higashinaruse.akita.jp
+honjo.akita.jp
+honjyo.akita.jp
+ikawa.akita.jp
+kamikoani.akita.jp
+kamioka.akita.jp
+katagami.akita.jp
+kazuno.akita.jp
+kitaakita.akita.jp
+kosaka.akita.jp
+kyowa.akita.jp
+misato.akita.jp
+mitane.akita.jp
+moriyoshi.akita.jp
+nikaho.akita.jp
+noshiro.akita.jp
+odate.akita.jp
+oga.akita.jp
+ogata.akita.jp
+semboku.akita.jp
+yokote.akita.jp
+yurihonjo.akita.jp
+aomori.aomori.jp
+gonohe.aomori.jp
+hachinohe.aomori.jp
+hashikami.aomori.jp
+hiranai.aomori.jp
+hirosaki.aomori.jp
+itayanagi.aomori.jp
+kuroishi.aomori.jp
+misawa.aomori.jp
+mutsu.aomori.jp
+nakadomari.aomori.jp
+noheji.aomori.jp
+oirase.aomori.jp
+owani.aomori.jp
+rokunohe.aomori.jp
+sannohe.aomori.jp
+shichinohe.aomori.jp
+shingo.aomori.jp
+takko.aomori.jp
+towada.aomori.jp
+tsugaru.aomori.jp
+tsuruta.aomori.jp
+abiko.chiba.jp
+asahi.chiba.jp
+chonan.chiba.jp
+chosei.chiba.jp
+choshi.chiba.jp
+chuo.chiba.jp
+funabashi.chiba.jp
+futtsu.chiba.jp
+hanamigawa.chiba.jp
+ichihara.chiba.jp
+ichikawa.chiba.jp
+ichinomiya.chiba.jp
+inzai.chiba.jp
+isumi.chiba.jp
+kamagaya.chiba.jp
+kamogawa.chiba.jp
+kashiwa.chiba.jp
+katori.chiba.jp
+katsuura.chiba.jp
+kimitsu.chiba.jp
+kisarazu.chiba.jp
+kozaki.chiba.jp
+kujukuri.chiba.jp
+kyonan.chiba.jp
+matsudo.chiba.jp
+midori.chiba.jp
+mihama.chiba.jp
+minamiboso.chiba.jp
+mobara.chiba.jp
+mutsuzawa.chiba.jp
+nagara.chiba.jp
+nagareyama.chiba.jp
+narashino.chiba.jp
+narita.chiba.jp
+noda.chiba.jp
+oamishirasato.chiba.jp
+omigawa.chiba.jp
+onjuku.chiba.jp
+otaki.chiba.jp
+sakae.chiba.jp
+sakura.chiba.jp
+shimofusa.chiba.jp
+shirako.chiba.jp
+shiroi.chiba.jp
+shisui.chiba.jp
+sodegaura.chiba.jp
+sosa.chiba.jp
+tako.chiba.jp
+tateyama.chiba.jp
+togane.chiba.jp
+tohnosho.chiba.jp
+tomisato.chiba.jp
+urayasu.chiba.jp
+yachimata.chiba.jp
+yachiyo.chiba.jp
+yokaichiba.chiba.jp
+yokoshibahikari.chiba.jp
+yotsukaido.chiba.jp
+ainan.ehime.jp
+honai.ehime.jp
+ikata.ehime.jp
+imabari.ehime.jp
+iyo.ehime.jp
+kamijima.ehime.jp
+kihoku.ehime.jp
+kumakogen.ehime.jp
+masaki.ehime.jp
+matsuno.ehime.jp
+matsuyama.ehime.jp
+namikata.ehime.jp
+niihama.ehime.jp
+ozu.ehime.jp
+saijo.ehime.jp
+seiyo.ehime.jp
+shikokuchuo.ehime.jp
+tobe.ehime.jp
+toon.ehime.jp
+uchiko.ehime.jp
+uwajima.ehime.jp
+yawatahama.ehime.jp
+echizen.fukui.jp
+eiheiji.fukui.jp
+fukui.fukui.jp
+ikeda.fukui.jp
+katsuyama.fukui.jp
+mihama.fukui.jp
+minamiechizen.fukui.jp
+obama.fukui.jp
+ohi.fukui.jp
+ono.fukui.jp
+sabae.fukui.jp
+sakai.fukui.jp
+takahama.fukui.jp
+tsuruga.fukui.jp
+wakasa.fukui.jp
+ashiya.fukuoka.jp
+buzen.fukuoka.jp
+chikugo.fukuoka.jp
+chikuho.fukuoka.jp
+chikujo.fukuoka.jp
+chikushino.fukuoka.jp
+chikuzen.fukuoka.jp
+chuo.fukuoka.jp
+dazaifu.fukuoka.jp
+fukuchi.fukuoka.jp
+hakata.fukuoka.jp
+higashi.fukuoka.jp
+hirokawa.fukuoka.jp
+hisayama.fukuoka.jp
+iizuka.fukuoka.jp
+inatsuki.fukuoka.jp
+kaho.fukuoka.jp
+kasuga.fukuoka.jp
+kasuya.fukuoka.jp
+kawara.fukuoka.jp
+keisen.fukuoka.jp
+koga.fukuoka.jp
+kurate.fukuoka.jp
+kurogi.fukuoka.jp
+kurume.fukuoka.jp
+minami.fukuoka.jp
+miyako.fukuoka.jp
+miyama.fukuoka.jp
+miyawaka.fukuoka.jp
+mizumaki.fukuoka.jp
+munakata.fukuoka.jp
+nakagawa.fukuoka.jp
+nakama.fukuoka.jp
+nishi.fukuoka.jp
+nogata.fukuoka.jp
+ogori.fukuoka.jp
+okagaki.fukuoka.jp
+okawa.fukuoka.jp
+oki.fukuoka.jp
+omuta.fukuoka.jp
+onga.fukuoka.jp
+onojo.fukuoka.jp
+oto.fukuoka.jp
+saigawa.fukuoka.jp
+sasaguri.fukuoka.jp
+shingu.fukuoka.jp
+shinyoshitomi.fukuoka.jp
+shonai.fukuoka.jp
+soeda.fukuoka.jp
+sue.fukuoka.jp
+tachiarai.fukuoka.jp
+tagawa.fukuoka.jp
+takata.fukuoka.jp
+toho.fukuoka.jp
+toyotsu.fukuoka.jp
+tsuiki.fukuoka.jp
+ukiha.fukuoka.jp
+umi.fukuoka.jp
+usui.fukuoka.jp
+yamada.fukuoka.jp
+yame.fukuoka.jp
+yanagawa.fukuoka.jp
+yukuhashi.fukuoka.jp
+aizubange.fukushima.jp
+aizumisato.fukushima.jp
+aizuwakamatsu.fukushima.jp
+asakawa.fukushima.jp
+bandai.fukushima.jp
+date.fukushima.jp
+fukushima.fukushima.jp
+furudono.fukushima.jp
+futaba.fukushima.jp
+hanawa.fukushima.jp
+higashi.fukushima.jp
+hirata.fukushima.jp
+hirono.fukushima.jp
+iitate.fukushima.jp
+inawashiro.fukushima.jp
+ishikawa.fukushima.jp
+iwaki.fukushima.jp
+izumizaki.fukushima.jp
+kagamiishi.fukushima.jp
+kaneyama.fukushima.jp
+kawamata.fukushima.jp
+kitakata.fukushima.jp
+kitashiobara.fukushima.jp
+koori.fukushima.jp
+koriyama.fukushima.jp
+kunimi.fukushima.jp
+miharu.fukushima.jp
+mishima.fukushima.jp
+namie.fukushima.jp
+nango.fukushima.jp
+nishiaizu.fukushima.jp
+nishigo.fukushima.jp
+okuma.fukushima.jp
+omotego.fukushima.jp
+ono.fukushima.jp
+otama.fukushima.jp
+samegawa.fukushima.jp
+shimogo.fukushima.jp
+shirakawa.fukushima.jp
+showa.fukushima.jp
+soma.fukushima.jp
+sukagawa.fukushima.jp
+taishin.fukushima.jp
+tamakawa.fukushima.jp
+tanagura.fukushima.jp
+tenei.fukushima.jp
+yabuki.fukushima.jp
+yamato.fukushima.jp
+yamatsuri.fukushima.jp
+yanaizu.fukushima.jp
+yugawa.fukushima.jp
+anpachi.gifu.jp
+ena.gifu.jp
+gifu.gifu.jp
+ginan.gifu.jp
+godo.gifu.jp
+gujo.gifu.jp
+hashima.gifu.jp
+hichiso.gifu.jp
+hida.gifu.jp
+higashishirakawa.gifu.jp
+ibigawa.gifu.jp
+ikeda.gifu.jp
+kakamigahara.gifu.jp
+kani.gifu.jp
+kasahara.gifu.jp
+kasamatsu.gifu.jp
+kawaue.gifu.jp
+kitagata.gifu.jp
+mino.gifu.jp
+minokamo.gifu.jp
+mitake.gifu.jp
+mizunami.gifu.jp
+motosu.gifu.jp
+nakatsugawa.gifu.jp
+ogaki.gifu.jp
+sakahogi.gifu.jp
+seki.gifu.jp
+sekigahara.gifu.jp
+shirakawa.gifu.jp
+tajimi.gifu.jp
+takayama.gifu.jp
+tarui.gifu.jp
+toki.gifu.jp
+tomika.gifu.jp
+wanouchi.gifu.jp
+yamagata.gifu.jp
+yaotsu.gifu.jp
+yoro.gifu.jp
+annaka.gunma.jp
+chiyoda.gunma.jp
+fujioka.gunma.jp
+higashiagatsuma.gunma.jp
+isesaki.gunma.jp
+itakura.gunma.jp
+kanna.gunma.jp
+kanra.gunma.jp
+katashina.gunma.jp
+kawaba.gunma.jp
+kiryu.gunma.jp
+kusatsu.gunma.jp
+maebashi.gunma.jp
+meiwa.gunma.jp
+midori.gunma.jp
+minakami.gunma.jp
+naganohara.gunma.jp
+nakanojo.gunma.jp
+nanmoku.gunma.jp
+numata.gunma.jp
+oizumi.gunma.jp
+ora.gunma.jp
+ota.gunma.jp
+shibukawa.gunma.jp
+shimonita.gunma.jp
+shinto.gunma.jp
+showa.gunma.jp
+takasaki.gunma.jp
+takayama.gunma.jp
+tamamura.gunma.jp
+tatebayashi.gunma.jp
+tomioka.gunma.jp
+tsukiyono.gunma.jp
+tsumagoi.gunma.jp
+ueno.gunma.jp
+yoshioka.gunma.jp
+asaminami.hiroshima.jp
+daiwa.hiroshima.jp
+etajima.hiroshima.jp
+fuchu.hiroshima.jp
+fukuyama.hiroshima.jp
+hatsukaichi.hiroshima.jp
+higashihiroshima.hiroshima.jp
+hongo.hiroshima.jp
+jinsekikogen.hiroshima.jp
+kaita.hiroshima.jp
+kui.hiroshima.jp
+kumano.hiroshima.jp
+kure.hiroshima.jp
+mihara.hiroshima.jp
+miyoshi.hiroshima.jp
+naka.hiroshima.jp
+onomichi.hiroshima.jp
+osakikamijima.hiroshima.jp
+otake.hiroshima.jp
+saka.hiroshima.jp
+sera.hiroshima.jp
+seranishi.hiroshima.jp
+shinichi.hiroshima.jp
+shobara.hiroshima.jp
+takehara.hiroshima.jp
+abashiri.hokkaido.jp
+abira.hokkaido.jp
+aibetsu.hokkaido.jp
+akabira.hokkaido.jp
+akkeshi.hokkaido.jp
+asahikawa.hokkaido.jp
+ashibetsu.hokkaido.jp
+ashoro.hokkaido.jp
+assabu.hokkaido.jp
+atsuma.hokkaido.jp
+bibai.hokkaido.jp
+biei.hokkaido.jp
+bifuka.hokkaido.jp
+bihoro.hokkaido.jp
+biratori.hokkaido.jp
+chippubetsu.hokkaido.jp
+chitose.hokkaido.jp
+date.hokkaido.jp
+ebetsu.hokkaido.jp
+embetsu.hokkaido.jp
+eniwa.hokkaido.jp
+erimo.hokkaido.jp
+esan.hokkaido.jp
+esashi.hokkaido.jp
+fukagawa.hokkaido.jp
+fukushima.hokkaido.jp
+furano.hokkaido.jp
+furubira.hokkaido.jp
+haboro.hokkaido.jp
+hakodate.hokkaido.jp
+hamatonbetsu.hokkaido.jp
+hidaka.hokkaido.jp
+higashikagura.hokkaido.jp
+higashikawa.hokkaido.jp
+hiroo.hokkaido.jp
+hokuryu.hokkaido.jp
+hokuto.hokkaido.jp
+honbetsu.hokkaido.jp
+horokanai.hokkaido.jp
+horonobe.hokkaido.jp
+ikeda.hokkaido.jp
+imakane.hokkaido.jp
+ishikari.hokkaido.jp
+iwamizawa.hokkaido.jp
+iwanai.hokkaido.jp
+kamifurano.hokkaido.jp
+kamikawa.hokkaido.jp
+kamishihoro.hokkaido.jp
+kamisunagawa.hokkaido.jp
+kamoenai.hokkaido.jp
+kayabe.hokkaido.jp
+kembuchi.hokkaido.jp
+kikonai.hokkaido.jp
+kimobetsu.hokkaido.jp
+kitahiroshima.hokkaido.jp
+kitami.hokkaido.jp
+kiyosato.hokkaido.jp
+koshimizu.hokkaido.jp
+kunneppu.hokkaido.jp
+kuriyama.hokkaido.jp
+kuromatsunai.hokkaido.jp
+kushiro.hokkaido.jp
+kutchan.hokkaido.jp
+kyowa.hokkaido.jp
+mashike.hokkaido.jp
+matsumae.hokkaido.jp
+mikasa.hokkaido.jp
+minamifurano.hokkaido.jp
+mombetsu.hokkaido.jp
+moseushi.hokkaido.jp
+mukawa.hokkaido.jp
+muroran.hokkaido.jp
+naie.hokkaido.jp
+nakagawa.hokkaido.jp
+nakasatsunai.hokkaido.jp
+nakatombetsu.hokkaido.jp
+nanae.hokkaido.jp
+nanporo.hokkaido.jp
+nayoro.hokkaido.jp
+nemuro.hokkaido.jp
+niikappu.hokkaido.jp
+niki.hokkaido.jp
+nishiokoppe.hokkaido.jp
+noboribetsu.hokkaido.jp
+numata.hokkaido.jp
+obihiro.hokkaido.jp
+obira.hokkaido.jp
+oketo.hokkaido.jp
+okoppe.hokkaido.jp
+otaru.hokkaido.jp
+otobe.hokkaido.jp
+otofuke.hokkaido.jp
+otoineppu.hokkaido.jp
+oumu.hokkaido.jp
+ozora.hokkaido.jp
+pippu.hokkaido.jp
+rankoshi.hokkaido.jp
+rebun.hokkaido.jp
+rikubetsu.hokkaido.jp
+rishiri.hokkaido.jp
+rishirifuji.hokkaido.jp
+saroma.hokkaido.jp
+sarufutsu.hokkaido.jp
+shakotan.hokkaido.jp
+shari.hokkaido.jp
+shibecha.hokkaido.jp
+shibetsu.hokkaido.jp
+shikabe.hokkaido.jp
+shikaoi.hokkaido.jp
+shimamaki.hokkaido.jp
+shimizu.hokkaido.jp
+shimokawa.hokkaido.jp
+shinshinotsu.hokkaido.jp
+shintoku.hokkaido.jp
+shiranuka.hokkaido.jp
+shiraoi.hokkaido.jp
+shiriuchi.hokkaido.jp
+sobetsu.hokkaido.jp
+sunagawa.hokkaido.jp
+taiki.hokkaido.jp
+takasu.hokkaido.jp
+takikawa.hokkaido.jp
+takinoue.hokkaido.jp
+teshikaga.hokkaido.jp
+tobetsu.hokkaido.jp
+tohma.hokkaido.jp
+tomakomai.hokkaido.jp
+tomari.hokkaido.jp
+toya.hokkaido.jp
+toyako.hokkaido.jp
+toyotomi.hokkaido.jp
+toyoura.hokkaido.jp
+tsubetsu.hokkaido.jp
+tsukigata.hokkaido.jp
+urakawa.hokkaido.jp
+urausu.hokkaido.jp
+uryu.hokkaido.jp
+utashinai.hokkaido.jp
+wakkanai.hokkaido.jp
+wassamu.hokkaido.jp
+yakumo.hokkaido.jp
+yoichi.hokkaido.jp
+aioi.hyogo.jp
+akashi.hyogo.jp
+ako.hyogo.jp
+amagasaki.hyogo.jp
+aogaki.hyogo.jp
+asago.hyogo.jp
+ashiya.hyogo.jp
+awaji.hyogo.jp
+fukusaki.hyogo.jp
+goshiki.hyogo.jp
+harima.hyogo.jp
+himeji.hyogo.jp
+ichikawa.hyogo.jp
+inagawa.hyogo.jp
+itami.hyogo.jp
+kakogawa.hyogo.jp
+kamigori.hyogo.jp
+kamikawa.hyogo.jp
+kasai.hyogo.jp
+kasuga.hyogo.jp
+kawanishi.hyogo.jp
+miki.hyogo.jp
+minamiawaji.hyogo.jp
+nishinomiya.hyogo.jp
+nishiwaki.hyogo.jp
+ono.hyogo.jp
+sanda.hyogo.jp
+sannan.hyogo.jp
+sasayama.hyogo.jp
+sayo.hyogo.jp
+shingu.hyogo.jp
+shinonsen.hyogo.jp
+shiso.hyogo.jp
+sumoto.hyogo.jp
+taishi.hyogo.jp
+taka.hyogo.jp
+takarazuka.hyogo.jp
+takasago.hyogo.jp
+takino.hyogo.jp
+tamba.hyogo.jp
+tatsuno.hyogo.jp
+toyooka.hyogo.jp
+yabu.hyogo.jp
+yashiro.hyogo.jp
+yoka.hyogo.jp
+yokawa.hyogo.jp
+ami.ibaraki.jp
+asahi.ibaraki.jp
+bando.ibaraki.jp
+chikusei.ibaraki.jp
+daigo.ibaraki.jp
+fujishiro.ibaraki.jp
+hitachi.ibaraki.jp
+hitachinaka.ibaraki.jp
+hitachiomiya.ibaraki.jp
+hitachiota.ibaraki.jp
+ibaraki.ibaraki.jp
+ina.ibaraki.jp
+inashiki.ibaraki.jp
+itako.ibaraki.jp
+iwama.ibaraki.jp
+joso.ibaraki.jp
+kamisu.ibaraki.jp
+kasama.ibaraki.jp
+kashima.ibaraki.jp
+kasumigaura.ibaraki.jp
+koga.ibaraki.jp
+miho.ibaraki.jp
+mito.ibaraki.jp
+moriya.ibaraki.jp
+naka.ibaraki.jp
+namegata.ibaraki.jp
+oarai.ibaraki.jp
+ogawa.ibaraki.jp
+omitama.ibaraki.jp
+ryugasaki.ibaraki.jp
+sakai.ibaraki.jp
+sakuragawa.ibaraki.jp
+shimodate.ibaraki.jp
+shimotsuma.ibaraki.jp
+shirosato.ibaraki.jp
+sowa.ibaraki.jp
+suifu.ibaraki.jp
+takahagi.ibaraki.jp
+tamatsukuri.ibaraki.jp
+tokai.ibaraki.jp
+tomobe.ibaraki.jp
+tone.ibaraki.jp
+toride.ibaraki.jp
+tsuchiura.ibaraki.jp
+tsukuba.ibaraki.jp
+uchihara.ibaraki.jp
+ushiku.ibaraki.jp
+yachiyo.ibaraki.jp
+yamagata.ibaraki.jp
+yawara.ibaraki.jp
+yuki.ibaraki.jp
+anamizu.ishikawa.jp
+hakui.ishikawa.jp
+hakusan.ishikawa.jp
+kaga.ishikawa.jp
+kahoku.ishikawa.jp
+kanazawa.ishikawa.jp
+kawakita.ishikawa.jp
+komatsu.ishikawa.jp
+nakanoto.ishikawa.jp
+nanao.ishikawa.jp
+nomi.ishikawa.jp
+nonoichi.ishikawa.jp
+noto.ishikawa.jp
+shika.ishikawa.jp
+suzu.ishikawa.jp
+tsubata.ishikawa.jp
+tsurugi.ishikawa.jp
+uchinada.ishikawa.jp
+wajima.ishikawa.jp
+fudai.iwate.jp
+fujisawa.iwate.jp
+hanamaki.iwate.jp
+hiraizumi.iwate.jp
+hirono.iwate.jp
+ichinohe.iwate.jp
+ichinoseki.iwate.jp
+iwaizumi.iwate.jp
+iwate.iwate.jp
+joboji.iwate.jp
+kamaishi.iwate.jp
+kanegasaki.iwate.jp
+karumai.iwate.jp
+kawai.iwate.jp
+kitakami.iwate.jp
+kuji.iwate.jp
+kunohe.iwate.jp
+kuzumaki.iwate.jp
+miyako.iwate.jp
+mizusawa.iwate.jp
+morioka.iwate.jp
+ninohe.iwate.jp
+noda.iwate.jp
+ofunato.iwate.jp
+oshu.iwate.jp
+otsuchi.iwate.jp
+rikuzentakata.iwate.jp
+shiwa.iwate.jp
+shizukuishi.iwate.jp
+sumita.iwate.jp
+tanohata.iwate.jp
+tono.iwate.jp
+yahaba.iwate.jp
+yamada.iwate.jp
+ayagawa.kagawa.jp
+higashikagawa.kagawa.jp
+kanonji.kagawa.jp
+kotohira.kagawa.jp
+manno.kagawa.jp
+marugame.kagawa.jp
+mitoyo.kagawa.jp
+naoshima.kagawa.jp
+sanuki.kagawa.jp
+tadotsu.kagawa.jp
+takamatsu.kagawa.jp
+tonosho.kagawa.jp
+uchinomi.kagawa.jp
+utazu.kagawa.jp
+zentsuji.kagawa.jp
+akune.kagoshima.jp
+amami.kagoshima.jp
+hioki.kagoshima.jp
+isa.kagoshima.jp
+isen.kagoshima.jp
+izumi.kagoshima.jp
+kagoshima.kagoshima.jp
+kanoya.kagoshima.jp
+kawanabe.kagoshima.jp
+kinko.kagoshima.jp
+kouyama.kagoshima.jp
+makurazaki.kagoshima.jp
+matsumoto.kagoshima.jp
+minamitane.kagoshima.jp
+nakatane.kagoshima.jp
+nishinoomote.kagoshima.jp
+satsumasendai.kagoshima.jp
+soo.kagoshima.jp
+tarumizu.kagoshima.jp
+yusui.kagoshima.jp
+aikawa.kanagawa.jp
+atsugi.kanagawa.jp
+ayase.kanagawa.jp
+chigasaki.kanagawa.jp
+ebina.kanagawa.jp
+fujisawa.kanagawa.jp
+hadano.kanagawa.jp
+hakone.kanagawa.jp
+hiratsuka.kanagawa.jp
+isehara.kanagawa.jp
+kaisei.kanagawa.jp
+kamakura.kanagawa.jp
+kiyokawa.kanagawa.jp
+matsuda.kanagawa.jp
+minamiashigara.kanagawa.jp
+miura.kanagawa.jp
+nakai.kanagawa.jp
+ninomiya.kanagawa.jp
+odawara.kanagawa.jp
+oi.kanagawa.jp
+oiso.kanagawa.jp
+sagamihara.kanagawa.jp
+samukawa.kanagawa.jp
+tsukui.kanagawa.jp
+yamakita.kanagawa.jp
+yamato.kanagawa.jp
+yokosuka.kanagawa.jp
+yugawara.kanagawa.jp
+zama.kanagawa.jp
+zushi.kanagawa.jp
+aki.kochi.jp
+geisei.kochi.jp
+hidaka.kochi.jp
+higashitsuno.kochi.jp
+ino.kochi.jp
+kagami.kochi.jp
+kami.kochi.jp
+kitagawa.kochi.jp
+kochi.kochi.jp
+mihara.kochi.jp
+motoyama.kochi.jp
+muroto.kochi.jp
+nahari.kochi.jp
+nakamura.kochi.jp
+nankoku.kochi.jp
+nishitosa.kochi.jp
+niyodogawa.kochi.jp
+ochi.kochi.jp
+okawa.kochi.jp
+otoyo.kochi.jp
+otsuki.kochi.jp
+sakawa.kochi.jp
+sukumo.kochi.jp
+susaki.kochi.jp
+tosa.kochi.jp
+tosashimizu.kochi.jp
+toyo.kochi.jp
+tsuno.kochi.jp
+umaji.kochi.jp
+yasuda.kochi.jp
+yusuhara.kochi.jp
+amakusa.kumamoto.jp
+arao.kumamoto.jp
+aso.kumamoto.jp
+choyo.kumamoto.jp
+gyokuto.kumamoto.jp
+hitoyoshi.kumamoto.jp
+kamiamakusa.kumamoto.jp
+kashima.kumamoto.jp
+kikuchi.kumamoto.jp
+kosa.kumamoto.jp
+kumamoto.kumamoto.jp
+mashiki.kumamoto.jp
+mifune.kumamoto.jp
+minamata.kumamoto.jp
+minamioguni.kumamoto.jp
+nagasu.kumamoto.jp
+nishihara.kumamoto.jp
+oguni.kumamoto.jp
+ozu.kumamoto.jp
+sumoto.kumamoto.jp
+takamori.kumamoto.jp
+uki.kumamoto.jp
+uto.kumamoto.jp
+yamaga.kumamoto.jp
+yamato.kumamoto.jp
+yatsushiro.kumamoto.jp
+ayabe.kyoto.jp
+fukuchiyama.kyoto.jp
+higashiyama.kyoto.jp
+ide.kyoto.jp
+ine.kyoto.jp
+joyo.kyoto.jp
+kameoka.kyoto.jp
+kamo.kyoto.jp
+kita.kyoto.jp
+kizu.kyoto.jp
+kumiyama.kyoto.jp
+kyotamba.kyoto.jp
+kyotanabe.kyoto.jp
+kyotango.kyoto.jp
+maizuru.kyoto.jp
+minami.kyoto.jp
+minamiyamashiro.kyoto.jp
+miyazu.kyoto.jp
+muko.kyoto.jp
+nagaokakyo.kyoto.jp
+nakagyo.kyoto.jp
+nantan.kyoto.jp
+oyamazaki.kyoto.jp
+sakyo.kyoto.jp
+seika.kyoto.jp
+tanabe.kyoto.jp
+uji.kyoto.jp
+ujitawara.kyoto.jp
+wazuka.kyoto.jp
+yamashina.kyoto.jp
+yawata.kyoto.jp
+asahi.mie.jp
+inabe.mie.jp
+ise.mie.jp
+kameyama.mie.jp
+kawagoe.mie.jp
+kiho.mie.jp
+kisosaki.mie.jp
+kiwa.mie.jp
+komono.mie.jp
+kumano.mie.jp
+kuwana.mie.jp
+matsusaka.mie.jp
+meiwa.mie.jp
+mihama.mie.jp
+minamiise.mie.jp
+misugi.mie.jp
+miyama.mie.jp
+nabari.mie.jp
+shima.mie.jp
+suzuka.mie.jp
+tado.mie.jp
+taiki.mie.jp
+taki.mie.jp
+tamaki.mie.jp
+toba.mie.jp
+tsu.mie.jp
+udono.mie.jp
+ureshino.mie.jp
+watarai.mie.jp
+yokkaichi.mie.jp
+furukawa.miyagi.jp
+higashimatsushima.miyagi.jp
+ishinomaki.miyagi.jp
+iwanuma.miyagi.jp
+kakuda.miyagi.jp
+kami.miyagi.jp
+kawasaki.miyagi.jp
+kesennuma.miyagi.jp
+marumori.miyagi.jp
+matsushima.miyagi.jp
+minamisanriku.miyagi.jp
+misato.miyagi.jp
+murata.miyagi.jp
+natori.miyagi.jp
+ogawara.miyagi.jp
+ohira.miyagi.jp
+onagawa.miyagi.jp
+osaki.miyagi.jp
+rifu.miyagi.jp
+semine.miyagi.jp
+shibata.miyagi.jp
+shichikashuku.miyagi.jp
+shikama.miyagi.jp
+shiogama.miyagi.jp
+shiroishi.miyagi.jp
+tagajo.miyagi.jp
+taiwa.miyagi.jp
+tome.miyagi.jp
+tomiya.miyagi.jp
+wakuya.miyagi.jp
+watari.miyagi.jp
+yamamoto.miyagi.jp
+zao.miyagi.jp
+aya.miyazaki.jp
+ebino.miyazaki.jp
+gokase.miyazaki.jp
+hyuga.miyazaki.jp
+kadogawa.miyazaki.jp
+kawaminami.miyazaki.jp
+kijo.miyazaki.jp
+kitagawa.miyazaki.jp
+kitakata.miyazaki.jp
+kitaura.miyazaki.jp
+kobayashi.miyazaki.jp
+kunitomi.miyazaki.jp
+kushima.miyazaki.jp
+mimata.miyazaki.jp
+miyakonojo.miyazaki.jp
+miyazaki.miyazaki.jp
+morotsuka.miyazaki.jp
+nichinan.miyazaki.jp
+nishimera.miyazaki.jp
+nobeoka.miyazaki.jp
+saito.miyazaki.jp
+shiiba.miyazaki.jp
+shintomi.miyazaki.jp
+takaharu.miyazaki.jp
+takanabe.miyazaki.jp
+takazaki.miyazaki.jp
+tsuno.miyazaki.jp
+achi.nagano.jp
+agematsu.nagano.jp
+anan.nagano.jp
+aoki.nagano.jp
+asahi.nagano.jp
+azumino.nagano.jp
+chikuhoku.nagano.jp
+chikuma.nagano.jp
+chino.nagano.jp
+fujimi.nagano.jp
+hakuba.nagano.jp
+hara.nagano.jp
+hiraya.nagano.jp
+iida.nagano.jp
+iijima.nagano.jp
+iiyama.nagano.jp
+iizuna.nagano.jp
+ikeda.nagano.jp
+ikusaka.nagano.jp
+ina.nagano.jp
+karuizawa.nagano.jp
+kawakami.nagano.jp
+kiso.nagano.jp
+kisofukushima.nagano.jp
+kitaaiki.nagano.jp
+komagane.nagano.jp
+komoro.nagano.jp
+matsukawa.nagano.jp
+matsumoto.nagano.jp
+miasa.nagano.jp
+minamiaiki.nagano.jp
+minamimaki.nagano.jp
+minamiminowa.nagano.jp
+minowa.nagano.jp
+miyada.nagano.jp
+miyota.nagano.jp
+mochizuki.nagano.jp
+nagano.nagano.jp
+nagawa.nagano.jp
+nagiso.nagano.jp
+nakagawa.nagano.jp
+nakano.nagano.jp
+nozawaonsen.nagano.jp
+obuse.nagano.jp
+ogawa.nagano.jp
+okaya.nagano.jp
+omachi.nagano.jp
+omi.nagano.jp
+ookuwa.nagano.jp
+ooshika.nagano.jp
+otaki.nagano.jp
+otari.nagano.jp
+sakae.nagano.jp
+sakaki.nagano.jp
+saku.nagano.jp
+sakuho.nagano.jp
+shimosuwa.nagano.jp
+shinanomachi.nagano.jp
+shiojiri.nagano.jp
+suwa.nagano.jp
+suzaka.nagano.jp
+takagi.nagano.jp
+takamori.nagano.jp
+takayama.nagano.jp
+tateshina.nagano.jp
+tatsuno.nagano.jp
+togakushi.nagano.jp
+togura.nagano.jp
+tomi.nagano.jp
+ueda.nagano.jp
+wada.nagano.jp
+yamagata.nagano.jp
+yamanouchi.nagano.jp
+yasaka.nagano.jp
+yasuoka.nagano.jp
+chijiwa.nagasaki.jp
+futsu.nagasaki.jp
+goto.nagasaki.jp
+hasami.nagasaki.jp
+hirado.nagasaki.jp
+iki.nagasaki.jp
+isahaya.nagasaki.jp
+kawatana.nagasaki.jp
+kuchinotsu.nagasaki.jp
+matsuura.nagasaki.jp
+nagasaki.nagasaki.jp
+obama.nagasaki.jp
+omura.nagasaki.jp
+oseto.nagasaki.jp
+saikai.nagasaki.jp
+sasebo.nagasaki.jp
+seihi.nagasaki.jp
+shimabara.nagasaki.jp
+shinkamigoto.nagasaki.jp
+togitsu.nagasaki.jp
+tsushima.nagasaki.jp
+unzen.nagasaki.jp
+ando.nara.jp
+gose.nara.jp
+heguri.nara.jp
+higashiyoshino.nara.jp
+ikaruga.nara.jp
+ikoma.nara.jp
+kamikitayama.nara.jp
+kanmaki.nara.jp
+kashiba.nara.jp
+kashihara.nara.jp
+katsuragi.nara.jp
+kawai.nara.jp
+kawakami.nara.jp
+kawanishi.nara.jp
+koryo.nara.jp
+kurotaki.nara.jp
+mitsue.nara.jp
+miyake.nara.jp
+nara.nara.jp
+nosegawa.nara.jp
+oji.nara.jp
+ouda.nara.jp
+oyodo.nara.jp
+sakurai.nara.jp
+sango.nara.jp
+shimoichi.nara.jp
+shimokitayama.nara.jp
+shinjo.nara.jp
+soni.nara.jp
+takatori.nara.jp
+tawaramoto.nara.jp
+tenkawa.nara.jp
+tenri.nara.jp
+uda.nara.jp
+yamatokoriyama.nara.jp
+yamatotakada.nara.jp
+yamazoe.nara.jp
+yoshino.nara.jp
+aga.niigata.jp
+agano.niigata.jp
+gosen.niigata.jp
+itoigawa.niigata.jp
+izumozaki.niigata.jp
+joetsu.niigata.jp
+kamo.niigata.jp
+kariwa.niigata.jp
+kashiwazaki.niigata.jp
+minamiuonuma.niigata.jp
+mitsuke.niigata.jp
+muika.niigata.jp
+murakami.niigata.jp
+myoko.niigata.jp
+nagaoka.niigata.jp
+niigata.niigata.jp
+ojiya.niigata.jp
+omi.niigata.jp
+sado.niigata.jp
+sanjo.niigata.jp
+seiro.niigata.jp
+seirou.niigata.jp
+sekikawa.niigata.jp
+shibata.niigata.jp
+tagami.niigata.jp
+tainai.niigata.jp
+tochio.niigata.jp
+tokamachi.niigata.jp
+tsubame.niigata.jp
+tsunan.niigata.jp
+uonuma.niigata.jp
+yahiko.niigata.jp
+yoita.niigata.jp
+yuzawa.niigata.jp
+beppu.oita.jp
+bungoono.oita.jp
+bungotakada.oita.jp
+hasama.oita.jp
+hiji.oita.jp
+himeshima.oita.jp
+hita.oita.jp
+kamitsue.oita.jp
+kokonoe.oita.jp
+kuju.oita.jp
+kunisaki.oita.jp
+kusu.oita.jp
+oita.oita.jp
+saiki.oita.jp
+taketa.oita.jp
+tsukumi.oita.jp
+usa.oita.jp
+usuki.oita.jp
+yufu.oita.jp
+akaiwa.okayama.jp
+asakuchi.okayama.jp
+bizen.okayama.jp
+hayashima.okayama.jp
+ibara.okayama.jp
+kagamino.okayama.jp
+kasaoka.okayama.jp
+kibichuo.okayama.jp
+kumenan.okayama.jp
+kurashiki.okayama.jp
+maniwa.okayama.jp
+misaki.okayama.jp
+nagi.okayama.jp
+niimi.okayama.jp
+nishiawakura.okayama.jp
+okayama.okayama.jp
+satosho.okayama.jp
+setouchi.okayama.jp
+shinjo.okayama.jp
+shoo.okayama.jp
+soja.okayama.jp
+takahashi.okayama.jp
+tamano.okayama.jp
+tsuyama.okayama.jp
+wake.okayama.jp
+yakage.okayama.jp
+aguni.okinawa.jp
+ginowan.okinawa.jp
+ginoza.okinawa.jp
+gushikami.okinawa.jp
+haebaru.okinawa.jp
+higashi.okinawa.jp
+hirara.okinawa.jp
+iheya.okinawa.jp
+ishigaki.okinawa.jp
+ishikawa.okinawa.jp
+itoman.okinawa.jp
+izena.okinawa.jp
+kadena.okinawa.jp
+kin.okinawa.jp
+kitadaito.okinawa.jp
+kitanakagusuku.okinawa.jp
+kumejima.okinawa.jp
+kunigami.okinawa.jp
+minamidaito.okinawa.jp
+motobu.okinawa.jp
+nago.okinawa.jp
+naha.okinawa.jp
+nakagusuku.okinawa.jp
+nakijin.okinawa.jp
+nanjo.okinawa.jp
+nishihara.okinawa.jp
+ogimi.okinawa.jp
+okinawa.okinawa.jp
+onna.okinawa.jp
+shimoji.okinawa.jp
+taketomi.okinawa.jp
+tarama.okinawa.jp
+tokashiki.okinawa.jp
+tomigusuku.okinawa.jp
+tonaki.okinawa.jp
+urasoe.okinawa.jp
+uruma.okinawa.jp
+yaese.okinawa.jp
+yomitan.okinawa.jp
+yonabaru.okinawa.jp
+yonaguni.okinawa.jp
+zamami.okinawa.jp
+abeno.osaka.jp
+chihayaakasaka.osaka.jp
+chuo.osaka.jp
+daito.osaka.jp
+fujiidera.osaka.jp
+habikino.osaka.jp
+hannan.osaka.jp
+higashiosaka.osaka.jp
+higashisumiyoshi.osaka.jp
+higashiyodogawa.osaka.jp
+hirakata.osaka.jp
+ibaraki.osaka.jp
+ikeda.osaka.jp
+izumi.osaka.jp
+izumiotsu.osaka.jp
+izumisano.osaka.jp
+kadoma.osaka.jp
+kaizuka.osaka.jp
+kanan.osaka.jp
+kashiwara.osaka.jp
+katano.osaka.jp
+kawachinagano.osaka.jp
+kishiwada.osaka.jp
+kita.osaka.jp
+kumatori.osaka.jp
+matsubara.osaka.jp
+minato.osaka.jp
+minoh.osaka.jp
+misaki.osaka.jp
+moriguchi.osaka.jp
+neyagawa.osaka.jp
+nishi.osaka.jp
+nose.osaka.jp
+osakasayama.osaka.jp
+sakai.osaka.jp
+sayama.osaka.jp
+sennan.osaka.jp
+settsu.osaka.jp
+shijonawate.osaka.jp
+shimamoto.osaka.jp
+suita.osaka.jp
+tadaoka.osaka.jp
+taishi.osaka.jp
+tajiri.osaka.jp
+takaishi.osaka.jp
+takatsuki.osaka.jp
+tondabayashi.osaka.jp
+toyonaka.osaka.jp
+toyono.osaka.jp
+yao.osaka.jp
+ariake.saga.jp
+arita.saga.jp
+fukudomi.saga.jp
+genkai.saga.jp
+hamatama.saga.jp
+hizen.saga.jp
+imari.saga.jp
+kamimine.saga.jp
+kanzaki.saga.jp
+karatsu.saga.jp
+kashima.saga.jp
+kitagata.saga.jp
+kitahata.saga.jp
+kiyama.saga.jp
+kouhoku.saga.jp
+kyuragi.saga.jp
+nishiarita.saga.jp
+ogi.saga.jp
+omachi.saga.jp
+ouchi.saga.jp
+saga.saga.jp
+shiroishi.saga.jp
+taku.saga.jp
+tara.saga.jp
+tosu.saga.jp
+yoshinogari.saga.jp
+arakawa.saitama.jp
+asaka.saitama.jp
+chichibu.saitama.jp
+fujimi.saitama.jp
+fujimino.saitama.jp
+fukaya.saitama.jp
+hanno.saitama.jp
+hanyu.saitama.jp
+hasuda.saitama.jp
+hatogaya.saitama.jp
+hatoyama.saitama.jp
+hidaka.saitama.jp
+higashichichibu.saitama.jp
+higashimatsuyama.saitama.jp
+honjo.saitama.jp
+ina.saitama.jp
+iruma.saitama.jp
+iwatsuki.saitama.jp
+kamiizumi.saitama.jp
+kamikawa.saitama.jp
+kamisato.saitama.jp
+kasukabe.saitama.jp
+kawagoe.saitama.jp
+kawaguchi.saitama.jp
+kawajima.saitama.jp
+kazo.saitama.jp
+kitamoto.saitama.jp
+koshigaya.saitama.jp
+kounosu.saitama.jp
+kuki.saitama.jp
+kumagaya.saitama.jp
+matsubushi.saitama.jp
+minano.saitama.jp
+misato.saitama.jp
+miyashiro.saitama.jp
+miyoshi.saitama.jp
+moroyama.saitama.jp
+nagatoro.saitama.jp
+namegawa.saitama.jp
+niiza.saitama.jp
+ogano.saitama.jp
+ogawa.saitama.jp
+ogose.saitama.jp
+okegawa.saitama.jp
+omiya.saitama.jp
+otaki.saitama.jp
+ranzan.saitama.jp
+ryokami.saitama.jp
+saitama.saitama.jp
+sakado.saitama.jp
+satte.saitama.jp
+sayama.saitama.jp
+shiki.saitama.jp
+shiraoka.saitama.jp
+soka.saitama.jp
+sugito.saitama.jp
+toda.saitama.jp
+tokigawa.saitama.jp
+tokorozawa.saitama.jp
+tsurugashima.saitama.jp
+urawa.saitama.jp
+warabi.saitama.jp
+yashio.saitama.jp
+yokoze.saitama.jp
+yono.saitama.jp
+yorii.saitama.jp
+yoshida.saitama.jp
+yoshikawa.saitama.jp
+yoshimi.saitama.jp
+aisho.shiga.jp
+gamo.shiga.jp
+higashiomi.shiga.jp
+hikone.shiga.jp
+koka.shiga.jp
+konan.shiga.jp
+kosei.shiga.jp
+koto.shiga.jp
+kusatsu.shiga.jp
+maibara.shiga.jp
+moriyama.shiga.jp
+nagahama.shiga.jp
+nishiazai.shiga.jp
+notogawa.shiga.jp
+omihachiman.shiga.jp
+otsu.shiga.jp
+ritto.shiga.jp
+ryuoh.shiga.jp
+takashima.shiga.jp
+takatsuki.shiga.jp
+torahime.shiga.jp
+toyosato.shiga.jp
+yasu.shiga.jp
+akagi.shimane.jp
+ama.shimane.jp
+gotsu.shimane.jp
+hamada.shimane.jp
+higashiizumo.shimane.jp
+hikawa.shimane.jp
+hikimi.shimane.jp
+izumo.shimane.jp
+kakinoki.shimane.jp
+masuda.shimane.jp
+matsue.shimane.jp
+misato.shimane.jp
+nishinoshima.shimane.jp
+ohda.shimane.jp
+okinoshima.shimane.jp
+okuizumo.shimane.jp
+shimane.shimane.jp
+tamayu.shimane.jp
+tsuwano.shimane.jp
+unnan.shimane.jp
+yakumo.shimane.jp
+yasugi.shimane.jp
+yatsuka.shimane.jp
+arai.shizuoka.jp
+atami.shizuoka.jp
+fuji.shizuoka.jp
+fujieda.shizuoka.jp
+fujikawa.shizuoka.jp
+fujinomiya.shizuoka.jp
+fukuroi.shizuoka.jp
+gotemba.shizuoka.jp
+haibara.shizuoka.jp
+hamamatsu.shizuoka.jp
+higashiizu.shizuoka.jp
+ito.shizuoka.jp
+iwata.shizuoka.jp
+izu.shizuoka.jp
+izunokuni.shizuoka.jp
+kakegawa.shizuoka.jp
+kannami.shizuoka.jp
+kawanehon.shizuoka.jp
+kawazu.shizuoka.jp
+kikugawa.shizuoka.jp
+kosai.shizuoka.jp
+makinohara.shizuoka.jp
+matsuzaki.shizuoka.jp
+minamiizu.shizuoka.jp
+mishima.shizuoka.jp
+morimachi.shizuoka.jp
+nishiizu.shizuoka.jp
+numazu.shizuoka.jp
+omaezaki.shizuoka.jp
+shimada.shizuoka.jp
+shimizu.shizuoka.jp
+shimoda.shizuoka.jp
+shizuoka.shizuoka.jp
+susono.shizuoka.jp
+yaizu.shizuoka.jp
+yoshida.shizuoka.jp
+ashikaga.tochigi.jp
+bato.tochigi.jp
+haga.tochigi.jp
+ichikai.tochigi.jp
+iwafune.tochigi.jp
+kaminokawa.tochigi.jp
+kanuma.tochigi.jp
+karasuyama.tochigi.jp
+kuroiso.tochigi.jp
+mashiko.tochigi.jp
+mibu.tochigi.jp
+moka.tochigi.jp
+motegi.tochigi.jp
+nasu.tochigi.jp
+nasushiobara.tochigi.jp
+nikko.tochigi.jp
+nishikata.tochigi.jp
+nogi.tochigi.jp
+ohira.tochigi.jp
+ohtawara.tochigi.jp
+oyama.tochigi.jp
+sakura.tochigi.jp
+sano.tochigi.jp
+shimotsuke.tochigi.jp
+shioya.tochigi.jp
+takanezawa.tochigi.jp
+tochigi.tochigi.jp
+tsuga.tochigi.jp
+ujiie.tochigi.jp
+utsunomiya.tochigi.jp
+yaita.tochigi.jp
+aizumi.tokushima.jp
+anan.tokushima.jp
+ichiba.tokushima.jp
+itano.tokushima.jp
+kainan.tokushima.jp
+komatsushima.tokushima.jp
+matsushige.tokushima.jp
+mima.tokushima.jp
+minami.tokushima.jp
+miyoshi.tokushima.jp
+mugi.tokushima.jp
+nakagawa.tokushima.jp
+naruto.tokushima.jp
+sanagochi.tokushima.jp
+shishikui.tokushima.jp
+tokushima.tokushima.jp
+wajiki.tokushima.jp
+adachi.tokyo.jp
+akiruno.tokyo.jp
+akishima.tokyo.jp
+aogashima.tokyo.jp
+arakawa.tokyo.jp
+bunkyo.tokyo.jp
+chiyoda.tokyo.jp
+chofu.tokyo.jp
+chuo.tokyo.jp
+edogawa.tokyo.jp
+fuchu.tokyo.jp
+fussa.tokyo.jp
+hachijo.tokyo.jp
+hachioji.tokyo.jp
+hamura.tokyo.jp
+higashikurume.tokyo.jp
+higashimurayama.tokyo.jp
+higashiyamato.tokyo.jp
+hino.tokyo.jp
+hinode.tokyo.jp
+hinohara.tokyo.jp
+inagi.tokyo.jp
+itabashi.tokyo.jp
+katsushika.tokyo.jp
+kita.tokyo.jp
+kiyose.tokyo.jp
+kodaira.tokyo.jp
+koganei.tokyo.jp
+kokubunji.tokyo.jp
+komae.tokyo.jp
+koto.tokyo.jp
+kouzushima.tokyo.jp
+kunitachi.tokyo.jp
+machida.tokyo.jp
+meguro.tokyo.jp
+minato.tokyo.jp
+mitaka.tokyo.jp
+mizuho.tokyo.jp
+musashimurayama.tokyo.jp
+musashino.tokyo.jp
+nakano.tokyo.jp
+nerima.tokyo.jp
+ogasawara.tokyo.jp
+okutama.tokyo.jp
+ome.tokyo.jp
+oshima.tokyo.jp
+ota.tokyo.jp
+setagaya.tokyo.jp
+shibuya.tokyo.jp
+shinagawa.tokyo.jp
+shinjuku.tokyo.jp
+suginami.tokyo.jp
+sumida.tokyo.jp
+tachikawa.tokyo.jp
+taito.tokyo.jp
+tama.tokyo.jp
+toshima.tokyo.jp
+chizu.tottori.jp
+hino.tottori.jp
+kawahara.tottori.jp
+koge.tottori.jp
+kotoura.tottori.jp
+misasa.tottori.jp
+nanbu.tottori.jp
+nichinan.tottori.jp
+sakaiminato.tottori.jp
+tottori.tottori.jp
+wakasa.tottori.jp
+yazu.tottori.jp
+yonago.tottori.jp
+asahi.toyama.jp
+fuchu.toyama.jp
+fukumitsu.toyama.jp
+funahashi.toyama.jp
+himi.toyama.jp
+imizu.toyama.jp
+inami.toyama.jp
+johana.toyama.jp
+kamiichi.toyama.jp
+kurobe.toyama.jp
+nakaniikawa.toyama.jp
+namerikawa.toyama.jp
+nanto.toyama.jp
+nyuzen.toyama.jp
+oyabe.toyama.jp
+taira.toyama.jp
+takaoka.toyama.jp
+tateyama.toyama.jp
+toga.toyama.jp
+tonami.toyama.jp
+toyama.toyama.jp
+unazuki.toyama.jp
+uozu.toyama.jp
+yamada.toyama.jp
+arida.wakayama.jp
+aridagawa.wakayama.jp
+gobo.wakayama.jp
+hashimoto.wakayama.jp
+hidaka.wakayama.jp
+hirogawa.wakayama.jp
+inami.wakayama.jp
+iwade.wakayama.jp
+kainan.wakayama.jp
+kamitonda.wakayama.jp
+katsuragi.wakayama.jp
+kimino.wakayama.jp
+kinokawa.wakayama.jp
+kitayama.wakayama.jp
+koya.wakayama.jp
+koza.wakayama.jp
+kozagawa.wakayama.jp
+kudoyama.wakayama.jp
+kushimoto.wakayama.jp
+mihama.wakayama.jp
+misato.wakayama.jp
+nachikatsuura.wakayama.jp
+shingu.wakayama.jp
+shirahama.wakayama.jp
+taiji.wakayama.jp
+tanabe.wakayama.jp
+wakayama.wakayama.jp
+yuasa.wakayama.jp
+yura.wakayama.jp
+asahi.yamagata.jp
+funagata.yamagata.jp
+higashine.yamagata.jp
+iide.yamagata.jp
+kahoku.yamagata.jp
+kaminoyama.yamagata.jp
+kaneyama.yamagata.jp
+kawanishi.yamagata.jp
+mamurogawa.yamagata.jp
+mikawa.yamagata.jp
+murayama.yamagata.jp
+nagai.yamagata.jp
+nakayama.yamagata.jp
+nanyo.yamagata.jp
+nishikawa.yamagata.jp
+obanazawa.yamagata.jp
+oe.yamagata.jp
+oguni.yamagata.jp
+ohkura.yamagata.jp
+oishida.yamagata.jp
+sagae.yamagata.jp
+sakata.yamagata.jp
+sakegawa.yamagata.jp
+shinjo.yamagata.jp
+shirataka.yamagata.jp
+shonai.yamagata.jp
+takahata.yamagata.jp
+tendo.yamagata.jp
+tozawa.yamagata.jp
+tsuruoka.yamagata.jp
+yamagata.yamagata.jp
+yamanobe.yamagata.jp
+yonezawa.yamagata.jp
+yuza.yamagata.jp
+abu.yamaguchi.jp
+hagi.yamaguchi.jp
+hikari.yamaguchi.jp
+hofu.yamaguchi.jp
+iwakuni.yamaguchi.jp
+kudamatsu.yamaguchi.jp
+mitou.yamaguchi.jp
+nagato.yamaguchi.jp
+oshima.yamaguchi.jp
+shimonoseki.yamaguchi.jp
+shunan.yamaguchi.jp
+tabuse.yamaguchi.jp
+tokuyama.yamaguchi.jp
+toyota.yamaguchi.jp
+ube.yamaguchi.jp
+yuu.yamaguchi.jp
+chuo.yamanashi.jp
+doshi.yamanashi.jp
+fuefuki.yamanashi.jp
+fujikawa.yamanashi.jp
+fujikawaguchiko.yamanashi.jp
+fujiyoshida.yamanashi.jp
+hayakawa.yamanashi.jp
+hokuto.yamanashi.jp
+ichikawamisato.yamanashi.jp
+kai.yamanashi.jp
+kofu.yamanashi.jp
+koshu.yamanashi.jp
+kosuge.yamanashi.jp
+minami-alps.yamanashi.jp
+minobu.yamanashi.jp
+nakamichi.yamanashi.jp
+nanbu.yamanashi.jp
+narusawa.yamanashi.jp
+nirasaki.yamanashi.jp
+nishikatsura.yamanashi.jp
+oshino.yamanashi.jp
+otsuki.yamanashi.jp
+showa.yamanashi.jp
+tabayama.yamanashi.jp
+tsuru.yamanashi.jp
+uenohara.yamanashi.jp
+yamanakako.yamanashi.jp
+yamanashi.yamanashi.jp
+
+// ke : http://www.kenic.or.ke/index.php?option=com_content&task=view&id=117&Itemid=145
+*.ke
+
+// kg : http://www.domain.kg/dmn_n.html
+kg
+org.kg
+net.kg
+com.kg
+edu.kg
+gov.kg
+mil.kg
+
+// kh : http://www.mptc.gov.kh/dns_registration.htm
+*.kh
+
+// ki : http://www.ki/dns/index.html
+ki
+edu.ki
+biz.ki
+net.ki
+org.ki
+gov.ki
+info.ki
+com.ki
+
+// km : http://en.wikipedia.org/wiki/.km
+// http://www.domaine.km/documents/charte.doc
+km
+org.km
+nom.km
+gov.km
+prd.km
+tm.km
+edu.km
+mil.km
+ass.km
+com.km
+// These are only mentioned as proposed suggestions at domaine.km, but
+// http://en.wikipedia.org/wiki/.km says they're available for registration:
+coop.km
+asso.km
+presse.km
+medecin.km
+notaires.km
+pharmaciens.km
+veterinaire.km
+gouv.km
+
+// kn : http://en.wikipedia.org/wiki/.kn
+// http://www.dot.kn/domainRules.html
+kn
+net.kn
+org.kn
+edu.kn
+gov.kn
+
+// kp : http://www.kcce.kp/en_index.php
+kp
+com.kp
+edu.kp
+gov.kp
+org.kp
+rep.kp
+tra.kp
+
+// kr : http://en.wikipedia.org/wiki/.kr
+// see also: http://domain.nida.or.kr/eng/registration.jsp
+kr
+ac.kr
+co.kr
+es.kr
+go.kr
+hs.kr
+kg.kr
+mil.kr
+ms.kr
+ne.kr
+or.kr
+pe.kr
+re.kr
+sc.kr
+// kr geographical names
+busan.kr
+chungbuk.kr
+chungnam.kr
+daegu.kr
+daejeon.kr
+gangwon.kr
+gwangju.kr
+gyeongbuk.kr
+gyeonggi.kr
+gyeongnam.kr
+incheon.kr
+jeju.kr
+jeonbuk.kr
+jeonnam.kr
+seoul.kr
+ulsan.kr
+
+// kw : http://en.wikipedia.org/wiki/.kw
+*.kw
+
+// ky : http://www.icta.ky/da_ky_reg_dom.php
+// Confirmed by registry <kysupport@perimeterusa.com> 2008-06-17
+ky
+edu.ky
+gov.ky
+com.ky
+org.ky
+net.ky
+
+// kz : http://en.wikipedia.org/wiki/.kz
+// see also: http://www.nic.kz/rules/index.jsp
+kz
+org.kz
+edu.kz
+net.kz
+gov.kz
+mil.kz
+com.kz
+
+// la : http://en.wikipedia.org/wiki/.la
+// Submitted by registry <gavin.brown@nic.la> 2008-06-10
+la
+int.la
+net.la
+info.la
+edu.la
+gov.la
+per.la
+com.la
+org.la
+
+// lb : http://en.wikipedia.org/wiki/.lb
+// Submitted by registry <randy@psg.com> 2008-06-17
+lb
+com.lb
+edu.lb
+gov.lb
+net.lb
+org.lb
+
+// lc : http://en.wikipedia.org/wiki/.lc
+// see also: http://www.nic.lc/rules.htm
+lc
+com.lc
+net.lc
+co.lc
+org.lc
+edu.lc
+gov.lc
+
+// li : http://en.wikipedia.org/wiki/.li
+li
+
+// lk : http://www.nic.lk/seclevpr.html
+lk
+gov.lk
+sch.lk
+net.lk
+int.lk
+com.lk
+org.lk
+edu.lk
+ngo.lk
+soc.lk
+web.lk
+ltd.lk
+assn.lk
+grp.lk
+hotel.lk
+ac.lk
+
+// lr : http://psg.com/dns/lr/lr.txt
+// Submitted by registry <randy@psg.com> 2008-06-17
+lr
+com.lr
+edu.lr
+gov.lr
+org.lr
+net.lr
+
+// ls : http://en.wikipedia.org/wiki/.ls
+ls
+co.ls
+org.ls
+
+// lt : http://en.wikipedia.org/wiki/.lt
+lt
+// gov.lt : http://www.gov.lt/index_en.php
+gov.lt
+
+// lu : http://www.dns.lu/en/
+lu
+
+// lv : http://www.nic.lv/DNS/En/generic.php
+lv
+com.lv
+edu.lv
+gov.lv
+org.lv
+mil.lv
+id.lv
+net.lv
+asn.lv
+conf.lv
+
+// ly : http://www.nic.ly/regulations.php
+ly
+com.ly
+net.ly
+gov.ly
+plc.ly
+edu.ly
+sch.ly
+med.ly
+org.ly
+id.ly
+
+// ma : http://en.wikipedia.org/wiki/.ma
+// http://www.anrt.ma/fr/admin/download/upload/file_fr782.pdf
+ma
+co.ma
+net.ma
+gov.ma
+org.ma
+ac.ma
+press.ma
+
+// mc : http://www.nic.mc/
+mc
+tm.mc
+asso.mc
+
+// md : http://en.wikipedia.org/wiki/.md
+md
+
+// me : http://en.wikipedia.org/wiki/.me
+me
+co.me
+net.me
+org.me
+edu.me
+ac.me
+gov.me
+its.me
+priv.me
+
+// mg : http://nic.mg/nicmg/?page_id=39
+mg
+org.mg
+nom.mg
+gov.mg
+prd.mg
+tm.mg
+edu.mg
+mil.mg
+com.mg
+co.mg
+
+// mh : http://en.wikipedia.org/wiki/.mh
+mh
+
+// mil : http://en.wikipedia.org/wiki/.mil
+mil
+
+// mk : http://en.wikipedia.org/wiki/.mk
+// see also: http://dns.marnet.net.mk/postapka.php
+mk
+com.mk
+org.mk
+net.mk
+edu.mk
+gov.mk
+inf.mk
+name.mk
+
+// ml : http://www.gobin.info/domainname/ml-template.doc
+// see also: http://en.wikipedia.org/wiki/.ml
+ml
+com.ml
+edu.ml
+gouv.ml
+gov.ml
+net.ml
+org.ml
+presse.ml
+
+// mm : http://en.wikipedia.org/wiki/.mm
+*.mm
+
+// mn : http://en.wikipedia.org/wiki/.mn
+mn
+gov.mn
+edu.mn
+org.mn
+
+// mo : http://www.monic.net.mo/
+mo
+com.mo
+net.mo
+org.mo
+edu.mo
+gov.mo
+
+// mobi : http://en.wikipedia.org/wiki/.mobi
+mobi
+
+// mp : http://www.dot.mp/
+// Confirmed by registry <dcamacho@saipan.com> 2008-06-17
+mp
+
+// mq : http://en.wikipedia.org/wiki/.mq
+mq
+
+// mr : http://en.wikipedia.org/wiki/.mr
+mr
+gov.mr
+
+// ms : http://www.nic.ms/pdf/MS_Domain_Name_Rules.pdf
+ms
+com.ms
+edu.ms
+gov.ms
+net.ms
+org.ms
+
+// mt : https://www.nic.org.mt/go/policy
+// Submitted by registry <help@nic.org.mt> 2013-11-19
+mt
+com.mt
+edu.mt
+net.mt
+org.mt
+
+// mu : http://en.wikipedia.org/wiki/.mu
+mu
+com.mu
+net.mu
+org.mu
+gov.mu
+ac.mu
+co.mu
+or.mu
+
+// museum : http://about.museum/naming/
+// http://index.museum/
+museum
+academy.museum
+agriculture.museum
+air.museum
+airguard.museum
+alabama.museum
+alaska.museum
+amber.museum
+ambulance.museum
+american.museum
+americana.museum
+americanantiques.museum
+americanart.museum
+amsterdam.museum
+and.museum
+annefrank.museum
+anthro.museum
+anthropology.museum
+antiques.museum
+aquarium.museum
+arboretum.museum
+archaeological.museum
+archaeology.museum
+architecture.museum
+art.museum
+artanddesign.museum
+artcenter.museum
+artdeco.museum
+arteducation.museum
+artgallery.museum
+arts.museum
+artsandcrafts.museum
+asmatart.museum
+assassination.museum
+assisi.museum
+association.museum
+astronomy.museum
+atlanta.museum
+austin.museum
+australia.museum
+automotive.museum
+aviation.museum
+axis.museum
+badajoz.museum
+baghdad.museum
+bahn.museum
+bale.museum
+baltimore.museum
+barcelona.museum
+baseball.museum
+basel.museum
+baths.museum
+bauern.museum
+beauxarts.museum
+beeldengeluid.museum
+bellevue.museum
+bergbau.museum
+berkeley.museum
+berlin.museum
+bern.museum
+bible.museum
+bilbao.museum
+bill.museum
+birdart.museum
+birthplace.museum
+bonn.museum
+boston.museum
+botanical.museum
+botanicalgarden.museum
+botanicgarden.museum
+botany.museum
+brandywinevalley.museum
+brasil.museum
+bristol.museum
+british.museum
+britishcolumbia.museum
+broadcast.museum
+brunel.museum
+brussel.museum
+brussels.museum
+bruxelles.museum
+building.museum
+burghof.museum
+bus.museum
+bushey.museum
+cadaques.museum
+california.museum
+cambridge.museum
+can.museum
+canada.museum
+capebreton.museum
+carrier.museum
+cartoonart.museum
+casadelamoneda.museum
+castle.museum
+castres.museum
+celtic.museum
+center.museum
+chattanooga.museum
+cheltenham.museum
+chesapeakebay.museum
+chicago.museum
+children.museum
+childrens.museum
+childrensgarden.museum
+chiropractic.museum
+chocolate.museum
+christiansburg.museum
+cincinnati.museum
+cinema.museum
+circus.museum
+civilisation.museum
+civilization.museum
+civilwar.museum
+clinton.museum
+clock.museum
+coal.museum
+coastaldefence.museum
+cody.museum
+coldwar.museum
+collection.museum
+colonialwilliamsburg.museum
+coloradoplateau.museum
+columbia.museum
+columbus.museum
+communication.museum
+communications.museum
+community.museum
+computer.museum
+computerhistory.museum
+comunicações.museum
+contemporary.museum
+contemporaryart.museum
+convent.museum
+copenhagen.museum
+corporation.museum
+correios-e-telecomunicações.museum
+corvette.museum
+costume.museum
+countryestate.museum
+county.museum
+crafts.museum
+cranbrook.museum
+creation.museum
+cultural.museum
+culturalcenter.museum
+culture.museum
+cyber.museum
+cymru.museum
+dali.museum
+dallas.museum
+database.museum
+ddr.museum
+decorativearts.museum
+delaware.museum
+delmenhorst.museum
+denmark.museum
+depot.museum
+design.museum
+detroit.museum
+dinosaur.museum
+discovery.museum
+dolls.museum
+donostia.museum
+durham.museum
+eastafrica.museum
+eastcoast.museum
+education.museum
+educational.museum
+egyptian.museum
+eisenbahn.museum
+elburg.museum
+elvendrell.museum
+embroidery.museum
+encyclopedic.museum
+england.museum
+entomology.museum
+environment.museum
+environmentalconservation.museum
+epilepsy.museum
+essex.museum
+estate.museum
+ethnology.museum
+exeter.museum
+exhibition.museum
+family.museum
+farm.museum
+farmequipment.museum
+farmers.museum
+farmstead.museum
+field.museum
+figueres.museum
+filatelia.museum
+film.museum
+fineart.museum
+finearts.museum
+finland.museum
+flanders.museum
+florida.museum
+force.museum
+fortmissoula.museum
+fortworth.museum
+foundation.museum
+francaise.museum
+frankfurt.museum
+franziskaner.museum
+freemasonry.museum
+freiburg.museum
+fribourg.museum
+frog.museum
+fundacio.museum
+furniture.museum
+gallery.museum
+garden.museum
+gateway.museum
+geelvinck.museum
+gemological.museum
+geology.museum
+georgia.museum
+giessen.museum
+glas.museum
+glass.museum
+gorge.museum
+grandrapids.museum
+graz.museum
+guernsey.museum
+halloffame.museum
+hamburg.museum
+handson.museum
+harvestcelebration.museum
+hawaii.museum
+health.museum
+heimatunduhren.museum
+hellas.museum
+helsinki.museum
+hembygdsforbund.museum
+heritage.museum
+histoire.museum
+historical.museum
+historicalsociety.museum
+historichouses.museum
+historisch.museum
+historisches.museum
+history.museum
+historyofscience.museum
+horology.museum
+house.museum
+humanities.museum
+illustration.museum
+imageandsound.museum
+indian.museum
+indiana.museum
+indianapolis.museum
+indianmarket.museum
+intelligence.museum
+interactive.museum
+iraq.museum
+iron.museum
+isleofman.museum
+jamison.museum
+jefferson.museum
+jerusalem.museum
+jewelry.museum
+jewish.museum
+jewishart.museum
+jfk.museum
+journalism.museum
+judaica.museum
+judygarland.museum
+juedisches.museum
+juif.museum
+karate.museum
+karikatur.museum
+kids.museum
+koebenhavn.museum
+koeln.museum
+kunst.museum
+kunstsammlung.museum
+kunstunddesign.museum
+labor.museum
+labour.museum
+lajolla.museum
+lancashire.museum
+landes.museum
+lans.museum
+läns.museum
+larsson.museum
+lewismiller.museum
+lincoln.museum
+linz.museum
+living.museum
+livinghistory.museum
+localhistory.museum
+london.museum
+losangeles.museum
+louvre.museum
+loyalist.museum
+lucerne.museum
+luxembourg.museum
+luzern.museum
+mad.museum
+madrid.museum
+mallorca.museum
+manchester.museum
+mansion.museum
+mansions.museum
+manx.museum
+marburg.museum
+maritime.museum
+maritimo.museum
+maryland.museum
+marylhurst.museum
+media.museum
+medical.museum
+medizinhistorisches.museum
+meeres.museum
+memorial.museum
+mesaverde.museum
+michigan.museum
+midatlantic.museum
+military.museum
+mill.museum
+miners.museum
+mining.museum
+minnesota.museum
+missile.museum
+missoula.museum
+modern.museum
+moma.museum
+money.museum
+monmouth.museum
+monticello.museum
+montreal.museum
+moscow.museum
+motorcycle.museum
+muenchen.museum
+muenster.museum
+mulhouse.museum
+muncie.museum
+museet.museum
+museumcenter.museum
+museumvereniging.museum
+music.museum
+national.museum
+nationalfirearms.museum
+nationalheritage.museum
+nativeamerican.museum
+naturalhistory.museum
+naturalhistorymuseum.museum
+naturalsciences.museum
+nature.museum
+naturhistorisches.museum
+natuurwetenschappen.museum
+naumburg.museum
+naval.museum
+nebraska.museum
+neues.museum
+newhampshire.museum
+newjersey.museum
+newmexico.museum
+newport.museum
+newspaper.museum
+newyork.museum
+niepce.museum
+norfolk.museum
+north.museum
+nrw.museum
+nuernberg.museum
+nuremberg.museum
+nyc.museum
+nyny.museum
+oceanographic.museum
+oceanographique.museum
+omaha.museum
+online.museum
+ontario.museum
+openair.museum
+oregon.museum
+oregontrail.museum
+otago.museum
+oxford.museum
+pacific.museum
+paderborn.museum
+palace.museum
+paleo.museum
+palmsprings.museum
+panama.museum
+paris.museum
+pasadena.museum
+pharmacy.museum
+philadelphia.museum
+philadelphiaarea.museum
+philately.museum
+phoenix.museum
+photography.museum
+pilots.museum
+pittsburgh.museum
+planetarium.museum
+plantation.museum
+plants.museum
+plaza.museum
+portal.museum
+portland.museum
+portlligat.museum
+posts-and-telecommunications.museum
+preservation.museum
+presidio.museum
+press.museum
+project.museum
+public.museum
+pubol.museum
+quebec.museum
+railroad.museum
+railway.museum
+research.museum
+resistance.museum
+riodejaneiro.museum
+rochester.museum
+rockart.museum
+roma.museum
+russia.museum
+saintlouis.museum
+salem.museum
+salvadordali.museum
+salzburg.museum
+sandiego.museum
+sanfrancisco.museum
+santabarbara.museum
+santacruz.museum
+santafe.museum
+saskatchewan.museum
+satx.museum
+savannahga.museum
+schlesisches.museum
+schoenbrunn.museum
+schokoladen.museum
+school.museum
+schweiz.museum
+science.museum
+scienceandhistory.museum
+scienceandindustry.museum
+sciencecenter.museum
+sciencecenters.museum
+science-fiction.museum
+sciencehistory.museum
+sciences.museum
+sciencesnaturelles.museum
+scotland.museum
+seaport.museum
+settlement.museum
+settlers.museum
+shell.museum
+sherbrooke.museum
+sibenik.museum
+silk.museum
+ski.museum
+skole.museum
+society.museum
+sologne.museum
+soundandvision.museum
+southcarolina.museum
+southwest.museum
+space.museum
+spy.museum
+square.museum
+stadt.museum
+stalbans.museum
+starnberg.museum
+state.museum
+stateofdelaware.museum
+station.museum
+steam.museum
+steiermark.museum
+stjohn.museum
+stockholm.museum
+stpetersburg.museum
+stuttgart.museum
+suisse.museum
+surgeonshall.museum
+surrey.museum
+svizzera.museum
+sweden.museum
+sydney.museum
+tank.museum
+tcm.museum
+technology.museum
+telekommunikation.museum
+television.museum
+texas.museum
+textile.museum
+theater.museum
+time.museum
+timekeeping.museum
+topology.museum
+torino.museum
+touch.museum
+town.museum
+transport.museum
+tree.museum
+trolley.museum
+trust.museum
+trustee.museum
+uhren.museum
+ulm.museum
+undersea.museum
+university.museum
+usa.museum
+usantiques.museum
+usarts.museum
+uscountryestate.museum
+usculture.museum
+usdecorativearts.museum
+usgarden.museum
+ushistory.museum
+ushuaia.museum
+uslivinghistory.museum
+utah.museum
+uvic.museum
+valley.museum
+vantaa.museum
+versailles.museum
+viking.museum
+village.museum
+virginia.museum
+virtual.museum
+virtuel.museum
+vlaanderen.museum
+volkenkunde.museum
+wales.museum
+wallonie.museum
+war.museum
+washingtondc.museum
+watchandclock.museum
+watch-and-clock.museum
+western.museum
+westfalen.museum
+whaling.museum
+wildlife.museum
+williamsburg.museum
+windmill.museum
+workshop.museum
+york.museum
+yorkshire.museum
+yosemite.museum
+youth.museum
+zoological.museum
+zoology.museum
+ירושלים.museum
+иком.museum
+
+// mv : http://en.wikipedia.org/wiki/.mv
+// "mv" included because, contra Wikipedia, google.mv exists.
+mv
+aero.mv
+biz.mv
+com.mv
+coop.mv
+edu.mv
+gov.mv
+info.mv
+int.mv
+mil.mv
+museum.mv
+name.mv
+net.mv
+org.mv
+pro.mv
+
+// mw : http://www.registrar.mw/
+mw
+ac.mw
+biz.mw
+co.mw
+com.mw
+coop.mw
+edu.mw
+gov.mw
+int.mw
+museum.mw
+net.mw
+org.mw
+
+// mx : http://www.nic.mx/
+// Submitted by registry <farias@nic.mx> 2008-06-19
+mx
+com.mx
+org.mx
+gob.mx
+edu.mx
+net.mx
+
+// my : http://www.mynic.net.my/
+my
+com.my
+net.my
+org.my
+gov.my
+edu.my
+mil.my
+name.my
+
+// mz : http://www.gobin.info/domainname/mz-template.doc
+*.mz
+!teledata.mz
+
+// na : http://www.na-nic.com.na/
+// http://www.info.na/domain/
+na
+info.na
+pro.na
+name.na
+school.na
+or.na
+dr.na
+us.na
+mx.na
+ca.na
+in.na
+cc.na
+tv.na
+ws.na
+mobi.na
+co.na
+com.na
+org.na
+
+// name : has 2nd-level tlds, but there's no list of them
+name
+
+// nc : http://www.cctld.nc/
+nc
+asso.nc
+
+// ne : http://en.wikipedia.org/wiki/.ne
+ne
+
+// net : http://en.wikipedia.org/wiki/.net
+net
+
+// nf : http://en.wikipedia.org/wiki/.nf
+nf
+com.nf
+net.nf
+per.nf
+rec.nf
+web.nf
+arts.nf
+firm.nf
+info.nf
+other.nf
+store.nf
+
+// ng : http://psg.com/dns/ng/
+ng
+com.ng
+edu.ng
+name.ng
+net.ng
+org.ng
+sch.ng
+gov.ng
+mil.ng
+mobi.ng
+
+// ni : http://www.nic.ni/dominios.htm
+*.ni
+
+// nl : http://en.wikipedia.org/wiki/.nl
+// https://www.sidn.nl/
+// ccTLD for the Netherlands
+nl
+
+// BV.nl will be a registry for dutch BV's (besloten vennootschap)
+bv.nl
+
+// no : http://www.norid.no/regelverk/index.en.html
+// The Norwegian registry has declined to notify us of updates. The web pages
+// referenced below are the official source of the data. There is also an
+// announce mailing list:
+// https://postlister.uninett.no/sympa/info/norid-diskusjon
+no
+// Norid generic domains : http://www.norid.no/regelverk/vedlegg-c.en.html
+fhs.no
+vgs.no
+fylkesbibl.no
+folkebibl.no
+museum.no
+idrett.no
+priv.no
+// Non-Norid generic domains : http://www.norid.no/regelverk/vedlegg-d.en.html
+mil.no
+stat.no
+dep.no
+kommune.no
+herad.no
+// no geographical names : http://www.norid.no/regelverk/vedlegg-b.en.html
+// counties
+aa.no
+ah.no
+bu.no
+fm.no
+hl.no
+hm.no
+jan-mayen.no
+mr.no
+nl.no
+nt.no
+of.no
+ol.no
+oslo.no
+rl.no
+sf.no
+st.no
+svalbard.no
+tm.no
+tr.no
+va.no
+vf.no
+// primary and lower secondary schools per county
+gs.aa.no
+gs.ah.no
+gs.bu.no
+gs.fm.no
+gs.hl.no
+gs.hm.no
+gs.jan-mayen.no
+gs.mr.no
+gs.nl.no
+gs.nt.no
+gs.of.no
+gs.ol.no
+gs.oslo.no
+gs.rl.no
+gs.sf.no
+gs.st.no
+gs.svalbard.no
+gs.tm.no
+gs.tr.no
+gs.va.no
+gs.vf.no
+// cities
+akrehamn.no
+åkrehamn.no
+algard.no
+ålgård.no
+arna.no
+brumunddal.no
+bryne.no
+bronnoysund.no
+brønnøysund.no
+drobak.no
+drøbak.no
+egersund.no
+fetsund.no
+floro.no
+florø.no
+fredrikstad.no
+hokksund.no
+honefoss.no
+hønefoss.no
+jessheim.no
+jorpeland.no
+jørpeland.no
+kirkenes.no
+kopervik.no
+krokstadelva.no
+langevag.no
+langevåg.no
+leirvik.no
+mjondalen.no
+mjøndalen.no
+mo-i-rana.no
+mosjoen.no
+mosjøen.no
+nesoddtangen.no
+orkanger.no
+osoyro.no
+osøyro.no
+raholt.no
+råholt.no
+sandnessjoen.no
+sandnessjøen.no
+skedsmokorset.no
+slattum.no
+spjelkavik.no
+stathelle.no
+stavern.no
+stjordalshalsen.no
+stjørdalshalsen.no
+tananger.no
+tranby.no
+vossevangen.no
+// communities
+afjord.no
+åfjord.no
+agdenes.no
+al.no
+ål.no
+alesund.no
+ålesund.no
+alstahaug.no
+alta.no
+áltá.no
+alaheadju.no
+álaheadju.no
+alvdal.no
+amli.no
+åmli.no
+amot.no
+åmot.no
+andebu.no
+andoy.no
+andøy.no
+andasuolo.no
+ardal.no
+årdal.no
+aremark.no
+arendal.no
+ås.no
+aseral.no
+åseral.no
+asker.no
+askim.no
+askvoll.no
+askoy.no
+askøy.no
+asnes.no
+åsnes.no
+audnedaln.no
+aukra.no
+aure.no
+aurland.no
+aurskog-holand.no
+aurskog-høland.no
+austevoll.no
+austrheim.no
+averoy.no
+averøy.no
+balestrand.no
+ballangen.no
+balat.no
+bálát.no
+balsfjord.no
+bahccavuotna.no
+báhccavuotna.no
+bamble.no
+bardu.no
+beardu.no
+beiarn.no
+bajddar.no
+bájddar.no
+baidar.no
+báidár.no
+berg.no
+bergen.no
+berlevag.no
+berlevåg.no
+bearalvahki.no
+bearalváhki.no
+bindal.no
+birkenes.no
+bjarkoy.no
+bjarkøy.no
+bjerkreim.no
+bjugn.no
+bodo.no
+bodø.no
+badaddja.no
+bådåddjå.no
+budejju.no
+bokn.no
+bremanger.no
+bronnoy.no
+brønnøy.no
+bygland.no
+bykle.no
+barum.no
+bærum.no
+bo.telemark.no
+bø.telemark.no
+bo.nordland.no
+bø.nordland.no
+bievat.no
+bievát.no
+bomlo.no
+bømlo.no
+batsfjord.no
+båtsfjord.no
+bahcavuotna.no
+báhcavuotna.no
+dovre.no
+drammen.no
+drangedal.no
+dyroy.no
+dyrøy.no
+donna.no
+dønna.no
+eid.no
+eidfjord.no
+eidsberg.no
+eidskog.no
+eidsvoll.no
+eigersund.no
+elverum.no
+enebakk.no
+engerdal.no
+etne.no
+etnedal.no
+evenes.no
+evenassi.no
+evenášši.no
+evje-og-hornnes.no
+farsund.no
+fauske.no
+fuossko.no
+fuoisku.no
+fedje.no
+fet.no
+finnoy.no
+finnøy.no
+fitjar.no
+fjaler.no
+fjell.no
+flakstad.no
+flatanger.no
+flekkefjord.no
+flesberg.no
+flora.no
+fla.no
+flå.no
+folldal.no
+forsand.no
+fosnes.no
+frei.no
+frogn.no
+froland.no
+frosta.no
+frana.no
+fræna.no
+froya.no
+frøya.no
+fusa.no
+fyresdal.no
+forde.no
+førde.no
+gamvik.no
+gangaviika.no
+gáŋgaviika.no
+gaular.no
+gausdal.no
+gildeskal.no
+gildeskål.no
+giske.no
+gjemnes.no
+gjerdrum.no
+gjerstad.no
+gjesdal.no
+gjovik.no
+gjøvik.no
+gloppen.no
+gol.no
+gran.no
+grane.no
+granvin.no
+gratangen.no
+grimstad.no
+grong.no
+kraanghke.no
+kråanghke.no
+grue.no
+gulen.no
+hadsel.no
+halden.no
+halsa.no
+hamar.no
+hamaroy.no
+habmer.no
+hábmer.no
+hapmir.no
+hápmir.no
+hammerfest.no
+hammarfeasta.no
+hámmárfeasta.no
+haram.no
+hareid.no
+harstad.no
+hasvik.no
+aknoluokta.no
+ákŋoluokta.no
+hattfjelldal.no
+aarborte.no
+haugesund.no
+hemne.no
+hemnes.no
+hemsedal.no
+heroy.more-og-romsdal.no
+herøy.møre-og-romsdal.no
+heroy.nordland.no
+herøy.nordland.no
+hitra.no
+hjartdal.no
+hjelmeland.no
+hobol.no
+hobøl.no
+hof.no
+hol.no
+hole.no
+holmestrand.no
+holtalen.no
+holtålen.no
+hornindal.no
+horten.no
+hurdal.no
+hurum.no
+hvaler.no
+hyllestad.no
+hagebostad.no
+hægebostad.no
+hoyanger.no
+høyanger.no
+hoylandet.no
+høylandet.no
+ha.no
+hå.no
+ibestad.no
+inderoy.no
+inderøy.no
+iveland.no
+jevnaker.no
+jondal.no
+jolster.no
+jølster.no
+karasjok.no
+karasjohka.no
+kárášjohka.no
+karlsoy.no
+galsa.no
+gálsá.no
+karmoy.no
+karmøy.no
+kautokeino.no
+guovdageaidnu.no
+klepp.no
+klabu.no
+klæbu.no
+kongsberg.no
+kongsvinger.no
+kragero.no
+kragerø.no
+kristiansand.no
+kristiansund.no
+krodsherad.no
+krødsherad.no
+kvalsund.no
+rahkkeravju.no
+ráhkkerávju.no
+kvam.no
+kvinesdal.no
+kvinnherad.no
+kviteseid.no
+kvitsoy.no
+kvitsøy.no
+kvafjord.no
+kvæfjord.no
+giehtavuoatna.no
+kvanangen.no
+kvænangen.no
+navuotna.no
+návuotna.no
+kafjord.no
+kåfjord.no
+gaivuotna.no
+gáivuotna.no
+larvik.no
+lavangen.no
+lavagis.no
+loabat.no
+loabát.no
+lebesby.no
+davvesiida.no
+leikanger.no
+leirfjord.no
+leka.no
+leksvik.no
+lenvik.no
+leangaviika.no
+leaŋgaviika.no
+lesja.no
+levanger.no
+lier.no
+lierne.no
+lillehammer.no
+lillesand.no
+lindesnes.no
+lindas.no
+lindås.no
+lom.no
+loppa.no
+lahppi.no
+láhppi.no
+lund.no
+lunner.no
+luroy.no
+lurøy.no
+luster.no
+lyngdal.no
+lyngen.no
+ivgu.no
+lardal.no
+lerdal.no
+lærdal.no
+lodingen.no
+lødingen.no
+lorenskog.no
+lørenskog.no
+loten.no
+løten.no
+malvik.no
+masoy.no
+måsøy.no
+muosat.no
+muosát.no
+mandal.no
+marker.no
+marnardal.no
+masfjorden.no
+meland.no
+meldal.no
+melhus.no
+meloy.no
+meløy.no
+meraker.no
+meråker.no
+moareke.no
+moåreke.no
+midsund.no
+midtre-gauldal.no
+modalen.no
+modum.no
+molde.no
+moskenes.no
+moss.no
+mosvik.no
+malselv.no
+målselv.no
+malatvuopmi.no
+málatvuopmi.no
+namdalseid.no
+aejrie.no
+namsos.no
+namsskogan.no
+naamesjevuemie.no
+nååmesjevuemie.no
+laakesvuemie.no
+nannestad.no
+narvik.no
+narviika.no
+naustdal.no
+nedre-eiker.no
+nes.akershus.no
+nes.buskerud.no
+nesna.no
+nesodden.no
+nesseby.no
+unjarga.no
+unjárga.no
+nesset.no
+nissedal.no
+nittedal.no
+nord-aurdal.no
+nord-fron.no
+nord-odal.no
+norddal.no
+nordkapp.no
+davvenjarga.no
+davvenjárga.no
+nordre-land.no
+nordreisa.no
+raisa.no
+ráisa.no
+nore-og-uvdal.no
+notodden.no
+naroy.no
+nærøy.no
+notteroy.no
+nøtterøy.no
+odda.no
+oksnes.no
+øksnes.no
+oppdal.no
+oppegard.no
+oppegård.no
+orkdal.no
+orland.no
+ørland.no
+orskog.no
+ørskog.no
+orsta.no
+ørsta.no
+os.hedmark.no
+os.hordaland.no
+osen.no
+osteroy.no
+osterøy.no
+ostre-toten.no
+østre-toten.no
+overhalla.no
+ovre-eiker.no
+øvre-eiker.no
+oyer.no
+øyer.no
+oygarden.no
+øygarden.no
+oystre-slidre.no
+øystre-slidre.no
+porsanger.no
+porsangu.no
+porsáŋgu.no
+porsgrunn.no
+radoy.no
+radøy.no
+rakkestad.no
+rana.no
+ruovat.no
+randaberg.no
+rauma.no
+rendalen.no
+rennebu.no
+rennesoy.no
+rennesøy.no
+rindal.no
+ringebu.no
+ringerike.no
+ringsaker.no
+rissa.no
+risor.no
+risør.no
+roan.no
+rollag.no
+rygge.no
+ralingen.no
+rælingen.no
+rodoy.no
+rødøy.no
+romskog.no
+rømskog.no
+roros.no
+røros.no
+rost.no
+røst.no
+royken.no
+røyken.no
+royrvik.no
+røyrvik.no
+rade.no
+råde.no
+salangen.no
+siellak.no
+saltdal.no
+salat.no
+sálát.no
+sálat.no
+samnanger.no
+sande.more-og-romsdal.no
+sande.møre-og-romsdal.no
+sande.vestfold.no
+sandefjord.no
+sandnes.no
+sandoy.no
+sandøy.no
+sarpsborg.no
+sauda.no
+sauherad.no
+sel.no
+selbu.no
+selje.no
+seljord.no
+sigdal.no
+siljan.no
+sirdal.no
+skaun.no
+skedsmo.no
+ski.no
+skien.no
+skiptvet.no
+skjervoy.no
+skjervøy.no
+skierva.no
+skiervá.no
+skjak.no
+skjåk.no
+skodje.no
+skanland.no
+skånland.no
+skanit.no
+skánit.no
+smola.no
+smøla.no
+snillfjord.no
+snasa.no
+snåsa.no
+snoasa.no
+snaase.no
+snåase.no
+sogndal.no
+sokndal.no
+sola.no
+solund.no
+songdalen.no
+sortland.no
+spydeberg.no
+stange.no
+stavanger.no
+steigen.no
+steinkjer.no
+stjordal.no
+stjørdal.no
+stokke.no
+stor-elvdal.no
+stord.no
+stordal.no
+storfjord.no
+omasvuotna.no
+strand.no
+stranda.no
+stryn.no
+sula.no
+suldal.no
+sund.no
+sunndal.no
+surnadal.no
+sveio.no
+svelvik.no
+sykkylven.no
+sogne.no
+søgne.no
+somna.no
+sømna.no
+sondre-land.no
+søndre-land.no
+sor-aurdal.no
+sør-aurdal.no
+sor-fron.no
+sør-fron.no
+sor-odal.no
+sør-odal.no
+sor-varanger.no
+sør-varanger.no
+matta-varjjat.no
+mátta-várjjat.no
+sorfold.no
+sørfold.no
+sorreisa.no
+sørreisa.no
+sorum.no
+sørum.no
+tana.no
+deatnu.no
+time.no
+tingvoll.no
+tinn.no
+tjeldsund.no
+dielddanuorri.no
+tjome.no
+tjøme.no
+tokke.no
+tolga.no
+torsken.no
+tranoy.no
+tranøy.no
+tromso.no
+tromsø.no
+tromsa.no
+romsa.no
+trondheim.no
+troandin.no
+trysil.no
+trana.no
+træna.no
+trogstad.no
+trøgstad.no
+tvedestrand.no
+tydal.no
+tynset.no
+tysfjord.no
+divtasvuodna.no
+divttasvuotna.no
+tysnes.no
+tysvar.no
+tysvær.no
+tonsberg.no
+tønsberg.no
+ullensaker.no
+ullensvang.no
+ulvik.no
+utsira.no
+vadso.no
+vadsø.no
+cahcesuolo.no
+čáhcesuolo.no
+vaksdal.no
+valle.no
+vang.no
+vanylven.no
+vardo.no
+vardø.no
+varggat.no
+várggát.no
+vefsn.no
+vaapste.no
+vega.no
+vegarshei.no
+vegårshei.no
+vennesla.no
+verdal.no
+verran.no
+vestby.no
+vestnes.no
+vestre-slidre.no
+vestre-toten.no
+vestvagoy.no
+vestvågøy.no
+vevelstad.no
+vik.no
+vikna.no
+vindafjord.no
+volda.no
+voss.no
+varoy.no
+værøy.no
+vagan.no
+vågan.no
+voagat.no
+vagsoy.no
+vågsøy.no
+vaga.no
+vågå.no
+valer.ostfold.no
+våler.østfold.no
+valer.hedmark.no
+våler.hedmark.no
+
+// np : http://www.mos.com.np/register.html
+*.np
+
+// nr : http://cenpac.net.nr/dns/index.html
+// Confirmed by registry <technician@cenpac.net.nr> 2008-06-17
+nr
+biz.nr
+info.nr
+gov.nr
+edu.nr
+org.nr
+net.nr
+com.nr
+
+// nu : http://en.wikipedia.org/wiki/.nu
+nu
+
+// nz : http://en.wikipedia.org/wiki/.nz
+// Confirmed by registry <jay@nzrs.net.nz> 2014-05-19
+nz
+ac.nz
+co.nz
+cri.nz
+geek.nz
+gen.nz
+govt.nz
+health.nz
+iwi.nz
+kiwi.nz
+maori.nz
+mil.nz
+māori.nz
+net.nz
+org.nz
+parliament.nz
+school.nz
+
+// om : http://en.wikipedia.org/wiki/.om
+om
+co.om
+com.om
+edu.om
+gov.om
+med.om
+museum.om
+net.om
+org.om
+pro.om
+
+// org : http://en.wikipedia.org/wiki/.org
+org
+
+// pa : http://www.nic.pa/
+// Some additional second level "domains" resolve directly as hostnames, such as
+// pannet.pa, so we add a rule for "pa".
+pa
+ac.pa
+gob.pa
+com.pa
+org.pa
+sld.pa
+edu.pa
+net.pa
+ing.pa
+abo.pa
+med.pa
+nom.pa
+
+// pe : https://www.nic.pe/InformeFinalComision.pdf
+pe
+edu.pe
+gob.pe
+nom.pe
+mil.pe
+org.pe
+com.pe
+net.pe
+
+// pf : http://www.gobin.info/domainname/formulaire-pf.pdf
+pf
+com.pf
+org.pf
+edu.pf
+
+// pg : http://en.wikipedia.org/wiki/.pg
+*.pg
+
+// ph : http://www.domains.ph/FAQ2.asp
+// Submitted by registry <jed@email.com.ph> 2008-06-13
+ph
+com.ph
+net.ph
+org.ph
+gov.ph
+edu.ph
+ngo.ph
+mil.ph
+i.ph
+
+// pk : http://pk5.pknic.net.pk/pk5/msgNamepk.PK
+pk
+com.pk
+net.pk
+edu.pk
+org.pk
+fam.pk
+biz.pk
+web.pk
+gov.pk
+gob.pk
+gok.pk
+gon.pk
+gop.pk
+gos.pk
+info.pk
+
+// pl http://www.dns.pl/english/index.html
+// updated by .PL registry on 2015-04-28
+pl
+com.pl
+net.pl
+org.pl
+// pl functional domains (http://www.dns.pl/english/index.html)
+aid.pl
+agro.pl
+atm.pl
+auto.pl
+biz.pl
+edu.pl
+gmina.pl
+gsm.pl
+info.pl
+mail.pl
+miasta.pl
+media.pl
+mil.pl
+nieruchomosci.pl
+nom.pl
+pc.pl
+powiat.pl
+priv.pl
+realestate.pl
+rel.pl
+sex.pl
+shop.pl
+sklep.pl
+sos.pl
+szkola.pl
+targi.pl
+tm.pl
+tourism.pl
+travel.pl
+turystyka.pl
+// Government domains
+gov.pl
+ap.gov.pl
+ic.gov.pl
+is.gov.pl
+us.gov.pl
+kmpsp.gov.pl
+kppsp.gov.pl
+kwpsp.gov.pl
+psp.gov.pl
+wskr.gov.pl
+kwp.gov.pl
+mw.gov.pl
+ug.gov.pl
+um.gov.pl
+umig.gov.pl
+ugim.gov.pl
+upow.gov.pl
+uw.gov.pl
+starostwo.gov.pl
+pa.gov.pl
+po.gov.pl
+psse.gov.pl
+pup.gov.pl
+rzgw.gov.pl
+sa.gov.pl
+so.gov.pl
+sr.gov.pl
+wsa.gov.pl
+sko.gov.pl
+uzs.gov.pl
+wiih.gov.pl
+winb.gov.pl
+pinb.gov.pl
+wios.gov.pl
+witd.gov.pl
+wzmiuw.gov.pl
+piw.gov.pl
+wiw.gov.pl
+griw.gov.pl
+wif.gov.pl
+oum.gov.pl
+sdn.gov.pl
+zp.gov.pl
+uppo.gov.pl
+mup.gov.pl
+wuoz.gov.pl
+konsulat.gov.pl
+oirm.gov.pl
+// pl regional domains (http://www.dns.pl/english/index.html)
+augustow.pl
+babia-gora.pl
+bedzin.pl
+beskidy.pl
+bialowieza.pl
+bialystok.pl
+bielawa.pl
+bieszczady.pl
+boleslawiec.pl
+bydgoszcz.pl
+bytom.pl
+cieszyn.pl
+czeladz.pl
+czest.pl
+dlugoleka.pl
+elblag.pl
+elk.pl
+glogow.pl
+gniezno.pl
+gorlice.pl
+grajewo.pl
+ilawa.pl
+jaworzno.pl
+jelenia-gora.pl
+jgora.pl
+kalisz.pl
+kazimierz-dolny.pl
+karpacz.pl
+kartuzy.pl
+kaszuby.pl
+katowice.pl
+kepno.pl
+ketrzyn.pl
+klodzko.pl
+kobierzyce.pl
+kolobrzeg.pl
+konin.pl
+konskowola.pl
+kutno.pl
+lapy.pl
+lebork.pl
+legnica.pl
+lezajsk.pl
+limanowa.pl
+lomza.pl
+lowicz.pl
+lubin.pl
+lukow.pl
+malbork.pl
+malopolska.pl
+mazowsze.pl
+mazury.pl
+mielec.pl
+mielno.pl
+mragowo.pl
+naklo.pl
+nowaruda.pl
+nysa.pl
+olawa.pl
+olecko.pl
+olkusz.pl
+olsztyn.pl
+opoczno.pl
+opole.pl
+ostroda.pl
+ostroleka.pl
+ostrowiec.pl
+ostrowwlkp.pl
+pila.pl
+pisz.pl
+podhale.pl
+podlasie.pl
+polkowice.pl
+pomorze.pl
+pomorskie.pl
+prochowice.pl
+pruszkow.pl
+przeworsk.pl
+pulawy.pl
+radom.pl
+rawa-maz.pl
+rybnik.pl
+rzeszow.pl
+sanok.pl
+sejny.pl
+slask.pl
+slupsk.pl
+sosnowiec.pl
+stalowa-wola.pl
+skoczow.pl
+starachowice.pl
+stargard.pl
+suwalki.pl
+swidnica.pl
+swiebodzin.pl
+swinoujscie.pl
+szczecin.pl
+szczytno.pl
+tarnobrzeg.pl
+tgory.pl
+turek.pl
+tychy.pl
+ustka.pl
+walbrzych.pl
+warmia.pl
+warszawa.pl
+waw.pl
+wegrow.pl
+wielun.pl
+wlocl.pl
+wloclawek.pl
+wodzislaw.pl
+wolomin.pl
+wroclaw.pl
+zachpomor.pl
+zagan.pl
+zarow.pl
+zgora.pl
+zgorzelec.pl
+
+// pm : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf
+pm
+
+// pn : http://www.government.pn/PnRegistry/policies.htm
+pn
+gov.pn
+co.pn
+org.pn
+edu.pn
+net.pn
+
+// post : http://en.wikipedia.org/wiki/.post
+post
+
+// pr : http://www.nic.pr/index.asp?f=1
+pr
+com.pr
+net.pr
+org.pr
+gov.pr
+edu.pr
+isla.pr
+pro.pr
+biz.pr
+info.pr
+name.pr
+// these aren't mentioned on nic.pr, but on http://en.wikipedia.org/wiki/.pr
+est.pr
+prof.pr
+ac.pr
+
+// pro : http://www.nic.pro/support_faq.htm
+pro
+aca.pro
+bar.pro
+cpa.pro
+jur.pro
+law.pro
+med.pro
+eng.pro
+
+// ps : http://en.wikipedia.org/wiki/.ps
+// http://www.nic.ps/registration/policy.html#reg
+ps
+edu.ps
+gov.ps
+sec.ps
+plo.ps
+com.ps
+org.ps
+net.ps
+
+// pt : http://online.dns.pt/dns/start_dns
+pt
+net.pt
+gov.pt
+org.pt
+edu.pt
+int.pt
+publ.pt
+com.pt
+nome.pt
+
+// pw : http://en.wikipedia.org/wiki/.pw
+pw
+co.pw
+ne.pw
+or.pw
+ed.pw
+go.pw
+belau.pw
+
+// py : http://www.nic.py/pautas.html#seccion_9
+// Confirmed by registry 2012-10-03
+py
+com.py
+coop.py
+edu.py
+gov.py
+mil.py
+net.py
+org.py
+
+// qa : http://domains.qa/en/
+qa
+com.qa
+edu.qa
+gov.qa
+mil.qa
+name.qa
+net.qa
+org.qa
+sch.qa
+
+// re : http://www.afnic.re/obtenir/chartes/nommage-re/annexe-descriptifs
+re
+com.re
+asso.re
+nom.re
+
+// ro : http://www.rotld.ro/
+ro
+com.ro
+org.ro
+tm.ro
+nt.ro
+nom.ro
+info.ro
+rec.ro
+arts.ro
+firm.ro
+store.ro
+www.ro
+
+// rs : http://en.wikipedia.org/wiki/.rs
+rs
+co.rs
+org.rs
+edu.rs
+ac.rs
+gov.rs
+in.rs
+
+// ru : http://www.cctld.ru/ru/docs/aktiv_8.php
+// Industry domains
+ru
+ac.ru
+com.ru
+edu.ru
+int.ru
+net.ru
+org.ru
+pp.ru
+// Geographical domains
+adygeya.ru
+altai.ru
+amur.ru
+arkhangelsk.ru
+astrakhan.ru
+bashkiria.ru
+belgorod.ru
+bir.ru
+bryansk.ru
+buryatia.ru
+cbg.ru
+chel.ru
+chelyabinsk.ru
+chita.ru
+chukotka.ru
+chuvashia.ru
+dagestan.ru
+dudinka.ru
+e-burg.ru
+grozny.ru
+irkutsk.ru
+ivanovo.ru
+izhevsk.ru
+jar.ru
+joshkar-ola.ru
+kalmykia.ru
+kaluga.ru
+kamchatka.ru
+karelia.ru
+kazan.ru
+kchr.ru
+kemerovo.ru
+khabarovsk.ru
+khakassia.ru
+khv.ru
+kirov.ru
+koenig.ru
+komi.ru
+kostroma.ru
+krasnoyarsk.ru
+kuban.ru
+kurgan.ru
+kursk.ru
+lipetsk.ru
+magadan.ru
+mari.ru
+mari-el.ru
+marine.ru
+mordovia.ru
+// mosreg.ru Bug 1090800 - removed at request of Aleksey Konstantinov <konstantinovav@mosreg.ru>
+msk.ru
+murmansk.ru
+nalchik.ru
+nnov.ru
+nov.ru
+novosibirsk.ru
+nsk.ru
+omsk.ru
+orenburg.ru
+oryol.ru
+palana.ru
+penza.ru
+perm.ru
+ptz.ru
+rnd.ru
+ryazan.ru
+sakhalin.ru
+samara.ru
+saratov.ru
+simbirsk.ru
+smolensk.ru
+spb.ru
+stavropol.ru
+stv.ru
+surgut.ru
+tambov.ru
+tatarstan.ru
+tom.ru
+tomsk.ru
+tsaritsyn.ru
+tsk.ru
+tula.ru
+tuva.ru
+tver.ru
+tyumen.ru
+udm.ru
+udmurtia.ru
+ulan-ude.ru
+vladikavkaz.ru
+vladimir.ru
+vladivostok.ru
+volgograd.ru
+vologda.ru
+voronezh.ru
+vrn.ru
+vyatka.ru
+yakutia.ru
+yamal.ru
+yaroslavl.ru
+yekaterinburg.ru
+yuzhno-sakhalinsk.ru
+// More geographical domains
+amursk.ru
+baikal.ru
+cmw.ru
+fareast.ru
+jamal.ru
+kms.ru
+k-uralsk.ru
+kustanai.ru
+kuzbass.ru
+magnitka.ru
+mytis.ru
+nakhodka.ru
+nkz.ru
+norilsk.ru
+oskol.ru
+pyatigorsk.ru
+rubtsovsk.ru
+snz.ru
+syzran.ru
+vdonsk.ru
+zgrad.ru
+// State domains
+gov.ru
+mil.ru
+// Technical domains
+test.ru
+
+// rw : http://www.nic.rw/cgi-bin/policy.pl
+rw
+gov.rw
+net.rw
+edu.rw
+ac.rw
+com.rw
+co.rw
+int.rw
+mil.rw
+gouv.rw
+
+// sa : http://www.nic.net.sa/
+sa
+com.sa
+net.sa
+org.sa
+gov.sa
+med.sa
+pub.sa
+edu.sa
+sch.sa
+
+// sb : http://www.sbnic.net.sb/
+// Submitted by registry <lee.humphries@telekom.com.sb> 2008-06-08
+sb
+com.sb
+edu.sb
+gov.sb
+net.sb
+org.sb
+
+// sc : http://www.nic.sc/
+sc
+com.sc
+gov.sc
+net.sc
+org.sc
+edu.sc
+
+// sd : http://www.isoc.sd/sudanic.isoc.sd/billing_pricing.htm
+// Submitted by registry <admin@isoc.sd> 2008-06-17
+sd
+com.sd
+net.sd
+org.sd
+edu.sd
+med.sd
+tv.sd
+gov.sd
+info.sd
+
+// se : http://en.wikipedia.org/wiki/.se
+// Submitted by registry <patrik.wallstrom@iis.se> 2014-03-18
+se
+a.se
+ac.se
+b.se
+bd.se
+brand.se
+c.se
+d.se
+e.se
+f.se
+fh.se
+fhsk.se
+fhv.se
+g.se
+h.se
+i.se
+k.se
+komforb.se
+kommunalforbund.se
+komvux.se
+l.se
+lanbib.se
+m.se
+n.se
+naturbruksgymn.se
+o.se
+org.se
+p.se
+parti.se
+pp.se
+press.se
+r.se
+s.se
+t.se
+tm.se
+u.se
+w.se
+x.se
+y.se
+z.se
+
+// sg : http://www.nic.net.sg/page/registration-policies-procedures-and-guidelines
+sg
+com.sg
+net.sg
+org.sg
+gov.sg
+edu.sg
+per.sg
+
+// sh : http://www.nic.sh/registrar.html
+sh
+com.sh
+net.sh
+gov.sh
+org.sh
+mil.sh
+
+// si : http://en.wikipedia.org/wiki/.si
+si
+
+// sj : No registrations at this time.
+// Submitted by registry <jarle@uninett.no> 2008-06-16
+sj
+
+// sk : http://en.wikipedia.org/wiki/.sk
+// list of 2nd level domains ?
+sk
+
+// sl : http://www.nic.sl
+// Submitted by registry <adam@neoip.com> 2008-06-12
+sl
+com.sl
+net.sl
+edu.sl
+gov.sl
+org.sl
+
+// sm : http://en.wikipedia.org/wiki/.sm
+sm
+
+// sn : http://en.wikipedia.org/wiki/.sn
+sn
+art.sn
+com.sn
+edu.sn
+gouv.sn
+org.sn
+perso.sn
+univ.sn
+
+// so : http://www.soregistry.com/
+so
+com.so
+net.so
+org.so
+
+// sr : http://en.wikipedia.org/wiki/.sr
+sr
+
+// st : http://www.nic.st/html/policyrules/
+st
+co.st
+com.st
+consulado.st
+edu.st
+embaixada.st
+gov.st
+mil.st
+net.st
+org.st
+principe.st
+saotome.st
+store.st
+
+// su : http://en.wikipedia.org/wiki/.su
+su
+adygeya.su
+arkhangelsk.su
+balashov.su
+bashkiria.su
+bryansk.su
+dagestan.su
+grozny.su
+ivanovo.su
+kalmykia.su
+kaluga.su
+karelia.su
+khakassia.su
+krasnodar.su
+kurgan.su
+lenug.su
+mordovia.su
+msk.su
+murmansk.su
+nalchik.su
+nov.su
+obninsk.su
+penza.su
+pokrovsk.su
+sochi.su
+spb.su
+togliatti.su
+troitsk.su
+tula.su
+tuva.su
+vladikavkaz.su
+vladimir.su
+vologda.su
+
+// sv : http://www.svnet.org.sv/niveldos.pdf
+sv
+com.sv
+edu.sv
+gob.sv
+org.sv
+red.sv
+
+// sx : http://en.wikipedia.org/wiki/.sx
+// Confirmed by registry <jcvignes@openregistry.com> 2012-05-31
+sx
+gov.sx
+
+// sy : http://en.wikipedia.org/wiki/.sy
+// see also: http://www.gobin.info/domainname/sy.doc
+sy
+edu.sy
+gov.sy
+net.sy
+mil.sy
+com.sy
+org.sy
+
+// sz : http://en.wikipedia.org/wiki/.sz
+// http://www.sispa.org.sz/
+sz
+co.sz
+ac.sz
+org.sz
+
+// tc : http://en.wikipedia.org/wiki/.tc
+tc
+
+// td : http://en.wikipedia.org/wiki/.td
+td
+
+// tel: http://en.wikipedia.org/wiki/.tel
+// http://www.telnic.org/
+tel
+
+// tf : http://en.wikipedia.org/wiki/.tf
+tf
+
+// tg : http://en.wikipedia.org/wiki/.tg
+// http://www.nic.tg/
+tg
+
+// th : http://en.wikipedia.org/wiki/.th
+// Submitted by registry <krit@thains.co.th> 2008-06-17
+th
+ac.th
+co.th
+go.th
+in.th
+mi.th
+net.th
+or.th
+
+// tj : http://www.nic.tj/policy.html
+tj
+ac.tj
+biz.tj
+co.tj
+com.tj
+edu.tj
+go.tj
+gov.tj
+int.tj
+mil.tj
+name.tj
+net.tj
+nic.tj
+org.tj
+test.tj
+web.tj
+
+// tk : http://en.wikipedia.org/wiki/.tk
+tk
+
+// tl : http://en.wikipedia.org/wiki/.tl
+tl
+gov.tl
+
+// tm : http://www.nic.tm/local.html
+tm
+com.tm
+co.tm
+org.tm
+net.tm
+nom.tm
+gov.tm
+mil.tm
+edu.tm
+
+// tn : http://en.wikipedia.org/wiki/.tn
+// http://whois.ati.tn/
+tn
+com.tn
+ens.tn
+fin.tn
+gov.tn
+ind.tn
+intl.tn
+nat.tn
+net.tn
+org.tn
+info.tn
+perso.tn
+tourism.tn
+edunet.tn
+rnrt.tn
+rns.tn
+rnu.tn
+mincom.tn
+agrinet.tn
+defense.tn
+turen.tn
+
+// to : http://en.wikipedia.org/wiki/.to
+// Submitted by registry <egullich@colo.to> 2008-06-17
+to
+com.to
+gov.to
+net.to
+org.to
+edu.to
+mil.to
+
+// tp : No registrations at this time.
+// Submitted by Ryan Sleevi <ryan.sleevi@gmail.com> 2014-01-03
+tp
+
+// subTLDs: https://www.nic.tr/forms/eng/policies.pdf
+// and: https://www.nic.tr/forms/politikalar.pdf
+// Submitted by <mehmetgurevin@gmail.com> 2014-07-19
+tr
+com.tr
+info.tr
+biz.tr
+net.tr
+org.tr
+web.tr
+gen.tr
+tv.tr
+av.tr
+dr.tr
+bbs.tr
+name.tr
+tel.tr
+gov.tr
+bel.tr
+pol.tr
+mil.tr
+k12.tr
+edu.tr
+kep.tr
+
+// Used by Northern Cyprus
+nc.tr
+
+// Used by government agencies of Northern Cyprus
+gov.nc.tr
+
+// travel : http://en.wikipedia.org/wiki/.travel
+travel
+
+// tt : http://www.nic.tt/
+tt
+co.tt
+com.tt
+org.tt
+net.tt
+biz.tt
+info.tt
+pro.tt
+int.tt
+coop.tt
+jobs.tt
+mobi.tt
+travel.tt
+museum.tt
+aero.tt
+name.tt
+gov.tt
+edu.tt
+
+// tv : http://en.wikipedia.org/wiki/.tv
+// Not listing any 2LDs as reserved since none seem to exist in practice,
+// Wikipedia notwithstanding.
+tv
+
+// tw : http://en.wikipedia.org/wiki/.tw
+tw
+edu.tw
+gov.tw
+mil.tw
+com.tw
+net.tw
+org.tw
+idv.tw
+game.tw
+ebiz.tw
+club.tw
+網路.tw
+組織.tw
+商業.tw
+
+// tz : http://www.tznic.or.tz/index.php/domains
+// Confirmed by registry <manager@tznic.or.tz> 2013-01-22
+tz
+ac.tz
+co.tz
+go.tz
+hotel.tz
+info.tz
+me.tz
+mil.tz
+mobi.tz
+ne.tz
+or.tz
+sc.tz
+tv.tz
+
+// ua : https://hostmaster.ua/policy/?ua
+// Submitted by registry <dk@cctld.ua> 2012-04-27
+ua
+// ua 2LD
+com.ua
+edu.ua
+gov.ua
+in.ua
+net.ua
+org.ua
+// ua geographic names
+// https://hostmaster.ua/2ld/
+cherkassy.ua
+cherkasy.ua
+chernigov.ua
+chernihiv.ua
+chernivtsi.ua
+chernovtsy.ua
+ck.ua
+cn.ua
+cr.ua
+crimea.ua
+cv.ua
+dn.ua
+dnepropetrovsk.ua
+dnipropetrovsk.ua
+dominic.ua
+donetsk.ua
+dp.ua
+if.ua
+ivano-frankivsk.ua
+kh.ua
+kharkiv.ua
+kharkov.ua
+kherson.ua
+khmelnitskiy.ua
+khmelnytskyi.ua
+kiev.ua
+kirovograd.ua
+km.ua
+kr.ua
+krym.ua
+ks.ua
+kv.ua
+kyiv.ua
+lg.ua
+lt.ua
+lugansk.ua
+lutsk.ua
+lv.ua
+lviv.ua
+mk.ua
+mykolaiv.ua
+nikolaev.ua
+od.ua
+odesa.ua
+odessa.ua
+pl.ua
+poltava.ua
+rivne.ua
+rovno.ua
+rv.ua
+sb.ua
+sebastopol.ua
+sevastopol.ua
+sm.ua
+sumy.ua
+te.ua
+ternopil.ua
+uz.ua
+uzhgorod.ua
+vinnica.ua
+vinnytsia.ua
+vn.ua
+volyn.ua
+yalta.ua
+zaporizhzhe.ua
+zaporizhzhia.ua
+zhitomir.ua
+zhytomyr.ua
+zp.ua
+zt.ua
+
+// Private registries in .ua
+co.ua
+pp.ua
+
+// ug : https://www.registry.co.ug/
+ug
+co.ug
+or.ug
+ac.ug
+sc.ug
+go.ug
+ne.ug
+com.ug
+org.ug
+
+// uk : http://en.wikipedia.org/wiki/.uk
+// Submitted by registry <Michael.Daly@nominet.org.uk>
+uk
+ac.uk
+co.uk
+gov.uk
+ltd.uk
+me.uk
+net.uk
+nhs.uk
+org.uk
+plc.uk
+police.uk
+*.sch.uk
+
+// us : http://en.wikipedia.org/wiki/.us
+us
+dni.us
+fed.us
+isa.us
+kids.us
+nsn.us
+// us geographic names
+ak.us
+al.us
+ar.us
+as.us
+az.us
+ca.us
+co.us
+ct.us
+dc.us
+de.us
+fl.us
+ga.us
+gu.us
+hi.us
+ia.us
+id.us
+il.us
+in.us
+ks.us
+ky.us
+la.us
+ma.us
+md.us
+me.us
+mi.us
+mn.us
+mo.us
+ms.us
+mt.us
+nc.us
+nd.us
+ne.us
+nh.us
+nj.us
+nm.us
+nv.us
+ny.us
+oh.us
+ok.us
+or.us
+pa.us
+pr.us
+ri.us
+sc.us
+sd.us
+tn.us
+tx.us
+ut.us
+vi.us
+vt.us
+va.us
+wa.us
+wi.us
+wv.us
+wy.us
+// The registrar notes several more specific domains available in each state,
+// such as state.*.us, dst.*.us, etc., but resolution of these is somewhat
+// haphazard; in some states these domains resolve as addresses, while in others
+// only subdomains are available, or even nothing at all. We include the
+// most common ones where it's clear that different sites are different
+// entities.
+k12.ak.us
+k12.al.us
+k12.ar.us
+k12.as.us
+k12.az.us
+k12.ca.us
+k12.co.us
+k12.ct.us
+k12.dc.us
+k12.de.us
+k12.fl.us
+k12.ga.us
+k12.gu.us
+// k12.hi.us Bug 614565 - Hawaii has a state-wide DOE login
+k12.ia.us
+k12.id.us
+k12.il.us
+k12.in.us
+k12.ks.us
+k12.ky.us
+k12.la.us
+k12.ma.us
+k12.md.us
+k12.me.us
+k12.mi.us
+k12.mn.us
+k12.mo.us
+k12.ms.us
+k12.mt.us
+k12.nc.us
+// k12.nd.us Bug 1028347 - Removed at request of Travis Rosso <trossow@nd.gov>
+k12.ne.us
+k12.nh.us
+k12.nj.us
+k12.nm.us
+k12.nv.us
+k12.ny.us
+k12.oh.us
+k12.ok.us
+k12.or.us
+k12.pa.us
+k12.pr.us
+k12.ri.us
+k12.sc.us
+// k12.sd.us Bug 934131 - Removed at request of James Booze <James.Booze@k12.sd.us>
+k12.tn.us
+k12.tx.us
+k12.ut.us
+k12.vi.us
+k12.vt.us
+k12.va.us
+k12.wa.us
+k12.wi.us
+// k12.wv.us Bug 947705 - Removed at request of Verne Britton <verne@wvnet.edu>
+k12.wy.us
+cc.ak.us
+cc.al.us
+cc.ar.us
+cc.as.us
+cc.az.us
+cc.ca.us
+cc.co.us
+cc.ct.us
+cc.dc.us
+cc.de.us
+cc.fl.us
+cc.ga.us
+cc.gu.us
+cc.hi.us
+cc.ia.us
+cc.id.us
+cc.il.us
+cc.in.us
+cc.ks.us
+cc.ky.us
+cc.la.us
+cc.ma.us
+cc.md.us
+cc.me.us
+cc.mi.us
+cc.mn.us
+cc.mo.us
+cc.ms.us
+cc.mt.us
+cc.nc.us
+cc.nd.us
+cc.ne.us
+cc.nh.us
+cc.nj.us
+cc.nm.us
+cc.nv.us
+cc.ny.us
+cc.oh.us
+cc.ok.us
+cc.or.us
+cc.pa.us
+cc.pr.us
+cc.ri.us
+cc.sc.us
+cc.sd.us
+cc.tn.us
+cc.tx.us
+cc.ut.us
+cc.vi.us
+cc.vt.us
+cc.va.us
+cc.wa.us
+cc.wi.us
+cc.wv.us
+cc.wy.us
+lib.ak.us
+lib.al.us
+lib.ar.us
+lib.as.us
+lib.az.us
+lib.ca.us
+lib.co.us
+lib.ct.us
+lib.dc.us
+lib.de.us
+lib.fl.us
+lib.ga.us
+lib.gu.us
+lib.hi.us
+lib.ia.us
+lib.id.us
+lib.il.us
+lib.in.us
+lib.ks.us
+lib.ky.us
+lib.la.us
+lib.ma.us
+lib.md.us
+lib.me.us
+lib.mi.us
+lib.mn.us
+lib.mo.us
+lib.ms.us
+lib.mt.us
+lib.nc.us
+lib.nd.us
+lib.ne.us
+lib.nh.us
+lib.nj.us
+lib.nm.us
+lib.nv.us
+lib.ny.us
+lib.oh.us
+lib.ok.us
+lib.or.us
+lib.pa.us
+lib.pr.us
+lib.ri.us
+lib.sc.us
+lib.sd.us
+lib.tn.us
+lib.tx.us
+lib.ut.us
+lib.vi.us
+lib.vt.us
+lib.va.us
+lib.wa.us
+lib.wi.us
+// lib.wv.us Bug 941670 - Removed at request of Larry W Arnold <arnold@wvlc.lib.wv.us>
+lib.wy.us
+// k12.ma.us contains school districts in Massachusetts. The 4LDs are
+// managed indepedently except for private (PVT), charter (CHTR) and
+// parochial (PAROCH) schools. Those are delegated dorectly to the
+// 5LD operators. <k12-ma-hostmaster _ at _ rsuc.gweep.net>
+pvt.k12.ma.us
+chtr.k12.ma.us
+paroch.k12.ma.us
+
+// uy : http://www.nic.org.uy/
+uy
+com.uy
+edu.uy
+gub.uy
+mil.uy
+net.uy
+org.uy
+
+// uz : http://www.reg.uz/
+uz
+co.uz
+com.uz
+net.uz
+org.uz
+
+// va : http://en.wikipedia.org/wiki/.va
+va
+
+// vc : http://en.wikipedia.org/wiki/.vc
+// Submitted by registry <kshah@ca.afilias.info> 2008-06-13
+vc
+com.vc
+net.vc
+org.vc
+gov.vc
+mil.vc
+edu.vc
+
+// ve : https://registro.nic.ve/
+// Confirmed by registry 2012-10-04
+// Updated 2014-05-20 - Bug 940478
+ve
+arts.ve
+co.ve
+com.ve
+e12.ve
+edu.ve
+firm.ve
+gob.ve
+gov.ve
+info.ve
+int.ve
+mil.ve
+net.ve
+org.ve
+rec.ve
+store.ve
+tec.ve
+web.ve
+
+// vg : http://en.wikipedia.org/wiki/.vg
+vg
+
+// vi : http://www.nic.vi/newdomainform.htm
+// http://www.nic.vi/Domain_Rules/body_domain_rules.html indicates some other
+// TLDs are "reserved", such as edu.vi and gov.vi, but doesn't actually say they
+// are available for registration (which they do not seem to be).
+vi
+co.vi
+com.vi
+k12.vi
+net.vi
+org.vi
+
+// vn : https://www.dot.vn/vnnic/vnnic/domainregistration.jsp
+vn
+com.vn
+net.vn
+org.vn
+edu.vn
+gov.vn
+int.vn
+ac.vn
+biz.vn
+info.vn
+name.vn
+pro.vn
+health.vn
+
+// vu : http://en.wikipedia.org/wiki/.vu
+// http://www.vunic.vu/
+vu
+com.vu
+edu.vu
+net.vu
+org.vu
+
+// wf : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf
+wf
+
+// ws : http://en.wikipedia.org/wiki/.ws
+// http://samoanic.ws/index.dhtml
+ws
+com.ws
+net.ws
+org.ws
+gov.ws
+edu.ws
+
+// yt : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf
+yt
+
+// IDN ccTLDs
+// When submitting patches, please maintain a sort by ISO 3166 ccTLD, then
+// U-label, and follow this format:
+// // A-Label ("<Latin renderings>", <language name>[, variant info]) : <ISO 3166 ccTLD>
+// // [sponsoring org]
+// U-Label
+
+// xn--mgbaam7a8h ("Emerat", Arabic) : AE
+// http://nic.ae/english/arabicdomain/rules.jsp
+امارات
+
+// xn--y9a3aq ("hye", Armenian) : AM
+// ISOC AM (operated by .am Registry)
+հայ
+
+// xn--54b7fta0cc ("Bangla", Bangla) : BD
+বাংলা
+
+// xn--90ais ("bel", Belarusian/Russian Cyrillic) : BY
+// Operated by .by registry
+бел
+
+// xn--fiqs8s ("Zhongguo/China", Chinese, Simplified) : CN
+// CNNIC
+// http://cnnic.cn/html/Dir/2005/10/11/3218.htm
+中国
+
+// xn--fiqz9s ("Zhongguo/China", Chinese, Traditional) : CN
+// CNNIC
+// http://cnnic.cn/html/Dir/2005/10/11/3218.htm
+中國
+
+// xn--lgbbat1ad8j ("Algeria/Al Jazair", Arabic) : DZ
+الجزائر
+
+// xn--wgbh1c ("Egypt/Masr", Arabic) : EG
+// http://www.dotmasr.eg/
+مصر
+
+// xn--node ("ge", Georgian Mkhedruli) : GE
+გე
+
+// xn--qxam ("el", Greek) : GR
+// Hellenic Ministry of Infrastructure, Transport, and Networks
+ελ
+
+// xn--j6w193g ("Hong Kong", Chinese) : HK
+// https://www2.hkirc.hk/register/rules.jsp
+香港
+
+// xn--h2brj9c ("Bharat", Devanagari) : IN
+// India
+भारत
+
+// xn--mgbbh1a71e ("Bharat", Arabic) : IN
+// India
+بھارت
+
+// xn--fpcrj9c3d ("Bharat", Telugu) : IN
+// India
+భారత్
+
+// xn--gecrj9c ("Bharat", Gujarati) : IN
+// India
+ભારત
+
+// xn--s9brj9c ("Bharat", Gurmukhi) : IN
+// India
+ਭਾਰਤ
+
+// xn--45brj9c ("Bharat", Bengali) : IN
+// India
+ভারত
+
+// xn--xkc2dl3a5ee0h ("India", Tamil) : IN
+// India
+இந்தியா
+
+// xn--mgba3a4f16a ("Iran", Persian) : IR
+ایران
+
+// xn--mgba3a4fra ("Iran", Arabic) : IR
+ايران
+
+// xn--mgbtx2b ("Iraq", Arabic) : IQ
+// Communications and Media Commission
+عراق
+
+// xn--mgbayh7gpa ("al-Ordon", Arabic) : JO
+// National Information Technology Center (NITC)
+// Royal Scientific Society, Al-Jubeiha
+الاردن
+
+// xn--3e0b707e ("Republic of Korea", Hangul) : KR
+한국
+
+// xn--80ao21a ("Kaz", Kazakh) : KZ
+қаз
+
+// xn--fzc2c9e2c ("Lanka", Sinhalese-Sinhala) : LK
+// http://nic.lk
+ලංකා
+
+// xn--xkc2al3hye2a ("Ilangai", Tamil) : LK
+// http://nic.lk
+இலங்கை
+
+// xn--mgbc0a9azcg ("Morocco/al-Maghrib", Arabic) : MA
+المغرب
+
+// xn--d1alf ("mkd", Macedonian) : MK
+// MARnet
+мкд
+
+// xn--l1acc ("mon", Mongolian) : MN
+мон
+
+// xn--mix891f ("Macao", Chinese, Traditional) : MO
+// MONIC / HNET Asia (Registry Operator for .mo)
+澳門
+
+// xn--mix082f ("Macao", Chinese, Simplified) : MO
+澳门
+
+// xn--mgbx4cd0ab ("Malaysia", Malay) : MY
+مليسيا
+
+// xn--mgb9awbf ("Oman", Arabic) : OM
+عمان
+
+// xn--mgbai9azgqp6j ("Pakistan", Urdu/Arabic) : PK
+پاکستان
+
+// xn--mgbai9a5eva00b ("Pakistan", Urdu/Arabic, variant) : PK
+پاكستان
+
+// xn--ygbi2ammx ("Falasteen", Arabic) : PS
+// The Palestinian National Internet Naming Authority (PNINA)
+// http://www.pnina.ps
+فلسطين
+
+// xn--90a3ac ("srb", Cyrillic) : RS
+// http://www.rnids.rs/en/the-.срб-domain
+срб
+пр.срб
+орг.срб
+обр.срб
+од.срб
+упр.срб
+ак.срб
+
+// xn--p1ai ("rf", Russian-Cyrillic) : RU
+// http://www.cctld.ru/en/docs/rulesrf.php
+рф
+
+// xn--wgbl6a ("Qatar", Arabic) : QA
+// http://www.ict.gov.qa/
+قطر
+
+// xn--mgberp4a5d4ar ("AlSaudiah", Arabic) : SA
+// http://www.nic.net.sa/
+السعودية
+
+// xn--mgberp4a5d4a87g ("AlSaudiah", Arabic, variant) : SA
+السعودیة
+
+// xn--mgbqly7c0a67fbc ("AlSaudiah", Arabic, variant) : SA
+السعودیۃ
+
+// xn--mgbqly7cvafr ("AlSaudiah", Arabic, variant) : SA
+السعوديه
+
+// xn--mgbpl2fh ("sudan", Arabic) : SD
+// Operated by .sd registry
+سودان
+
+// xn--yfro4i67o Singapore ("Singapore", Chinese) : SG
+新加坡
+
+// xn--clchc0ea0b2g2a9gcd ("Singapore", Tamil) : SG
+சிங்கப்பூர்
+
+// xn--ogbpf8fl ("Syria", Arabic) : SY
+سورية
+
+// xn--mgbtf8fl ("Syria", Arabic, variant) : SY
+سوريا
+
+// xn--o3cw4h ("Thai", Thai) : TH
+// http://www.thnic.co.th
+ไทย
+
+// xn--pgbs0dh ("Tunisia", Arabic) : TN
+// http://nic.tn
+تونس
+
+// xn--kpry57d ("Taiwan", Chinese, Traditional) : TW
+// http://www.twnic.net/english/dn/dn_07a.htm
+台灣
+
+// xn--kprw13d ("Taiwan", Chinese, Simplified) : TW
+// http://www.twnic.net/english/dn/dn_07a.htm
+台湾
+
+// xn--nnx388a ("Taiwan", Chinese, variant) : TW
+臺灣
+
+// xn--j1amh ("ukr", Cyrillic) : UA
+укр
+
+// xn--mgb2ddes ("AlYemen", Arabic) : YE
+اليمن
+
+// xxx : http://icmregistry.com
+xxx
+
+// ye : http://www.y.net.ye/services/domain_name.htm
+*.ye
+
+// za : http://www.zadna.org.za/content/page/domain-information
+ac.za
+agrica.za
+alt.za
+co.za
+edu.za
+gov.za
+grondar.za
+law.za
+mil.za
+net.za
+ngo.za
+nis.za
+nom.za
+org.za
+school.za
+tm.za
+web.za
+
+// zm : http://en.wikipedia.org/wiki/.zm
+*.zm
+
+// zw : http://en.wikipedia.org/wiki/.zw
+*.zw
+
+
+// List of new gTLDs imported from https://newgtlds.icann.org/newgtlds.csv on 2015-07-27T22:08:32Z
+
+// aaa : 2015-02-26 American Automobile Association, Inc.
+aaa
+
+// aarp : 2015-05-21 AARP
+aarp
+
+// abb : 2014-10-24 ABB Ltd
+abb
+
+// abbott : 2014-07-24 Abbott Laboratories, Inc.
+abbott
+
+// able : 2015-06-25 Able Inc.
+able
+
+// abogado : 2014-04-24 Top Level Domain Holdings Limited
+abogado
+
+// academy : 2013-11-07 Half Oaks, LLC
+academy
+
+// accenture : 2014-08-15 Accenture plc
+accenture
+
+// accountant : 2014-11-20 dot Accountant Limited
+accountant
+
+// accountants : 2014-03-20 Knob Town, LLC
+accountants
+
+// aco : 2015-01-08 ACO Severin Ahlmann GmbH & Co. KG
+aco
+
+// active : 2014-05-01 The Active Network, Inc
+active
+
+// actor : 2013-12-12 United TLD Holdco Ltd.
+actor
+
+// adac : 2015-07-16 Allgemeiner Deutscher Automobil-Club e.V. (ADAC)
+adac
+
+// ads : 2014-12-04 Charleston Road Registry Inc.
+ads
+
+// adult : 2014-10-16 ICM Registry AD LLC
+adult
+
+// aeg : 2015-03-19 Aktiebolaget Electrolux
+aeg
+
+// aetna : 2015-05-21 Aetna Life Insurance Company
+aetna
+
+// afamilycompany : 2015-07-23 Johnson Shareholdings, Inc.
+afamilycompany
+
+// afl : 2014-10-02 Australian Football League
+afl
+
+// africa : 2014-03-24 ZA Central Registry NPC trading as Registry.Africa
+africa
+
+// africamagic : 2015-03-05 Electronic Media Network (Pty) Ltd
+africamagic
+
+// agakhan : 2015-04-23 Fondation Aga Khan (Aga Khan Foundation)
+agakhan
+
+// agency : 2013-11-14 Steel Falls, LLC
+agency
+
+// aig : 2014-12-18 American International Group, Inc.
+aig
+
+// airforce : 2014-03-06 United TLD Holdco Ltd.
+airforce
+
+// airtel : 2014-10-24 Bharti Airtel Limited
+airtel
+
+// akdn : 2015-04-23 Fondation Aga Khan (Aga Khan Foundation)
+akdn
+
+// alibaba : 2015-01-15 Alibaba Group Holding Limited
+alibaba
+
+// alipay : 2015-01-15 Alibaba Group Holding Limited
+alipay
+
+// allfinanz : 2014-07-03 Allfinanz Deutsche Vermögensberatung Aktiengesellschaft
+allfinanz
+
+// ally : 2015-06-18 Ally Financial Inc.
+ally
+
+// alsace : 2014-07-02 REGION D ALSACE
+alsace
+
+// americanfamily : 2015-07-23 AmFam, Inc.
+americanfamily
+
+// amfam : 2015-07-23 AmFam, Inc.
+amfam
+
+// amica : 2015-05-28 Amica Mutual Insurance Company
+amica
+
+// amsterdam : 2014-07-24 Gemeente Amsterdam
+amsterdam
+
+// analytics : 2014-12-18 Campus IP LLC
+analytics
+
+// android : 2014-08-07 Charleston Road Registry Inc.
+android
+
+// anquan : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD.
+anquan
+
+// apartments : 2014-12-11 June Maple, LLC
+apartments
+
+// app : 2015-05-14 Charleston Road Registry Inc.
+app
+
+// apple : 2015-05-14 Apple Inc.
+apple
+
+// aquarelle : 2014-07-24 Aquarelle.com
+aquarelle
+
+// aramco : 2014-11-20 Aramco Services Company
+aramco
+
+// archi : 2014-02-06 STARTING DOT LIMITED
+archi
+
+// army : 2014-03-06 United TLD Holdco Ltd.
+army
+
+// arte : 2014-12-11 Association Relative à la Télévision Européenne G.E.I.E.
+arte
+
+// associates : 2014-03-06 Baxter Hill, LLC
+associates
+
+// attorney : 2014-03-20
+attorney
+
+// auction : 2014-03-20
+auction
+
+// audi : 2015-05-21 AUDI Aktiengesellschaft
+audi
+
+// audible : 2015-06-25 Amazon EU S.à r.l.
+audible
+
+// audio : 2014-03-20 Uniregistry, Corp.
+audio
+
+// author : 2014-12-18 Amazon EU S.à r.l.
+author
+
+// auto : 2014-11-13
+auto
+
+// autos : 2014-01-09 DERAutos, LLC
+autos
+
+// avianca : 2015-01-08 Aerovias del Continente Americano S.A. Avianca
+avianca
+
+// aws : 2015-06-25 Amazon EU S.à r.l.
+aws
+
+// axa : 2013-12-19 AXA SA
+axa
+
+// azure : 2014-12-18 Microsoft Corporation
+azure
+
+// baby : 2015-04-09 Johnson & Johnson Services, Inc.
+baby
+
+// baidu : 2015-01-08 Baidu, Inc.
+baidu
+
+// band : 2014-06-12
+band
+
+// bank : 2014-09-25 fTLD Registry Services LLC
+bank
+
+// bar : 2013-12-12 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable
+bar
+
+// barcelona : 2014-07-24 Municipi de Barcelona
+barcelona
+
+// barclaycard : 2014-11-20 Barclays Bank PLC
+barclaycard
+
+// barclays : 2014-11-20 Barclays Bank PLC
+barclays
+
+// barefoot : 2015-06-11 Gallo Vineyards, Inc.
+barefoot
+
+// bargains : 2013-11-14 Half Hallow, LLC
+bargains
+
+// bauhaus : 2014-04-17 Werkhaus GmbH
+bauhaus
+
+// bayern : 2014-01-23 Bayern Connect GmbH
+bayern
+
+// bbc : 2014-12-18 British Broadcasting Corporation
+bbc
+
+// bbt : 2015-07-23 BB&T Corporation
+bbt
+
+// bbva : 2014-10-02 BANCO BILBAO VIZCAYA ARGENTARIA, S.A.
+bbva
+
+// bcg : 2015-04-02 The Boston Consulting Group, Inc.
+bcg
+
+// bcn : 2014-07-24 Municipi de Barcelona
+bcn
+
+// beats : 2015-05-14 Beats Electronics, LLC
+beats
+
+// beer : 2014-01-09 Top Level Domain Holdings Limited
+beer
+
+// bentley : 2014-12-18 Bentley Motors Limited
+bentley
+
+// berlin : 2013-10-31 dotBERLIN GmbH & Co. KG
+berlin
+
+// best : 2013-12-19 BestTLD Pty Ltd
+best
+
+// bet : 2015-05-07 Afilias plc
+bet
+
+// bharti : 2014-01-09 Bharti Enterprises (Holding) Private Limited
+bharti
+
+// bible : 2014-06-19 American Bible Society
+bible
+
+// bid : 2013-12-19 dot Bid Limited
+bid
+
+// bike : 2013-08-27 Grand Hollow, LLC
+bike
+
+// bing : 2014-12-18 Microsoft Corporation
+bing
+
+// bingo : 2014-12-04 Sand Cedar, LLC
+bingo
+
+// bio : 2014-03-06 STARTING DOT LIMITED
+bio
+
+// black : 2014-01-16 Afilias Limited
+black
+
+// blackfriday : 2014-01-16 Uniregistry, Corp.
+blackfriday
+
+// blanco : 2015-07-16 BLANCO GmbH + Co KG
+blanco
+
+// blog : 2015-05-14 PRIMER NIVEL S.A.
+blog
+
+// bloomberg : 2014-07-17 Bloomberg IP Holdings LLC
+bloomberg
+
+// blue : 2013-11-07 Afilias Limited
+blue
+
+// bms : 2014-10-30 Bristol-Myers Squibb Company
+bms
+
+// bmw : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft
+bmw
+
+// bnl : 2014-07-24 Banca Nazionale del Lavoro
+bnl
+
+// bnpparibas : 2014-05-29 BNP Paribas
+bnpparibas
+
+// boats : 2014-12-04 DERBoats, LLC
+boats
+
+// boehringer : 2015-07-09 Boehringer Ingelheim International GmbH
+boehringer
+
+// bom : 2014-10-16 Núcleo de Informação e Coordenação do Ponto BR - NIC.br
+bom
+
+// bond : 2014-06-05 Bond University Limited
+bond
+
+// boo : 2014-01-30 Charleston Road Registry Inc.
+boo
+
+// booking : 2015-07-16 Booking.com B.V.
+booking
+
+// boots : 2015-01-08 THE BOOTS COMPANY PLC
+boots
+
+// bosch : 2015-06-18 Robert Bosch GMBH
+bosch
+
+// bostik : 2015-05-28 Bostik SA
+bostik
+
+// bot : 2014-12-18 Amazon EU S.à r.l.
+bot
+
+// boutique : 2013-11-14 Over Galley, LLC
+boutique
+
+// bradesco : 2014-12-18 Banco Bradesco S.A.
+bradesco
+
+// bridgestone : 2014-12-18 Bridgestone Corporation
+bridgestone
+
+// broadway : 2014-12-22 Celebrate Broadway, Inc.
+broadway
+
+// broker : 2014-12-11 IG Group Holdings PLC
+broker
+
+// brother : 2015-01-29 Brother Industries, Ltd.
+brother
+
+// brussels : 2014-02-06 DNS.be vzw
+brussels
+
+// budapest : 2013-11-21 Top Level Domain Holdings Limited
+budapest
+
+// bugatti : 2015-07-23 Bugatti International SA
+bugatti
+
+// build : 2013-11-07 Plan Bee LLC
+build
+
+// builders : 2013-11-07 Atomic Madison, LLC
+builders
+
+// business : 2013-11-07 Spring Cross, LLC
+business
+
+// buy : 2014-12-18 Amazon EU S.à r.l.
+buy
+
+// buzz : 2013-10-02 DOTSTRATEGY CO.
+buzz
+
+// bzh : 2014-02-27 Association www.bzh
+bzh
+
+// cab : 2013-10-24 Half Sunset, LLC
+cab
+
+// cafe : 2015-02-11 Pioneer Canyon, LLC
+cafe
+
+// cal : 2014-07-24 Charleston Road Registry Inc.
+cal
+
+// call : 2014-12-18 Amazon EU S.à r.l.
+call
+
+// camera : 2013-08-27 Atomic Maple, LLC
+camera
+
+// camp : 2013-11-07 Delta Dynamite, LLC
+camp
+
+// cancerresearch : 2014-05-15 Australian Cancer Research Foundation
+cancerresearch
+
+// canon : 2014-09-12 Canon Inc.
+canon
+
+// capetown : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry
+capetown
+
+// capital : 2014-03-06 Delta Mill, LLC
+capital
+
+// car : 2015-01-22
+car
+
+// caravan : 2013-12-12 Caravan International, Inc.
+caravan
+
+// cards : 2013-12-05 Foggy Hollow, LLC
+cards
+
+// care : 2014-03-06 Goose Cross
+care
+
+// career : 2013-10-09 dotCareer LLC
+career
+
+// careers : 2013-10-02 Wild Corner, LLC
+careers
+
+// cars : 2014-11-13
+cars
+
+// cartier : 2014-06-23 Richemont DNS Inc.
+cartier
+
+// casa : 2013-11-21 Top Level Domain Holdings Limited
+casa
+
+// cash : 2014-03-06 Delta Lake, LLC
+cash
+
+// casino : 2014-12-18 Binky Sky, LLC
+casino
+
+// catering : 2013-12-05 New Falls. LLC
+catering
+
+// cba : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA
+cba
+
+// cbn : 2014-08-22 The Christian Broadcasting Network, Inc.
+cbn
+
+// cbre : 2015-07-02 CBRE, Inc.
+cbre
+
+// ceb : 2015-04-09 The Corporate Executive Board Company
+ceb
+
+// center : 2013-11-07 Tin Mill, LLC
+center
+
+// ceo : 2013-11-07 CEOTLD Pty Ltd
+ceo
+
+// cern : 2014-06-05 European Organization for Nuclear Research ("CERN")
+cern
+
+// cfa : 2014-08-28 CFA Institute
+cfa
+
+// cfd : 2014-12-11 IG Group Holdings PLC
+cfd
+
+// chanel : 2015-04-09 Chanel International B.V.
+chanel
+
+// channel : 2014-05-08 Charleston Road Registry Inc.
+channel
+
+// chase : 2015-04-30 JPMorgan Chase & Co.
+chase
+
+// chat : 2014-12-04 Sand Fields, LLC
+chat
+
+// cheap : 2013-11-14 Sand Cover, LLC
+cheap
+
+// chintai : 2015-06-11 CHINTAI Corporation
+chintai
+
+// chloe : 2014-10-16 Richemont DNS Inc.
+chloe
+
+// christmas : 2013-11-21 Uniregistry, Corp.
+christmas
+
+// chrome : 2014-07-24 Charleston Road Registry Inc.
+chrome
+
+// church : 2014-02-06 Holly Fields, LLC
+church
+
+// cipriani : 2015-02-19 Hotel Cipriani Srl
+cipriani
+
+// circle : 2014-12-18 Amazon EU S.à r.l.
+circle
+
+// cisco : 2014-12-22 Cisco Technology, Inc.
+cisco
+
+// citadel : 2015-07-23 Citadel Domain LLC
+citadel
+
+// citic : 2014-01-09 CITIC Group Corporation
+citic
+
+// city : 2014-05-29 Snow Sky, LLC
+city
+
+// cityeats : 2014-12-11 Lifestyle Domain Holdings, Inc.
+cityeats
+
+// claims : 2014-03-20 Black Corner, LLC
+claims
+
+// cleaning : 2013-12-05 Fox Shadow, LLC
+cleaning
+
+// click : 2014-06-05 Uniregistry, Corp.
+click
+
+// clinic : 2014-03-20 Goose Park, LLC
+clinic
+
+// clothing : 2013-08-27 Steel Lake, LLC
+clothing
+
+// cloud : 2015-04-16 ARUBA S.p.A.
+cloud
+
+// club : 2013-11-08 .CLUB DOMAINS, LLC
+club
+
+// clubmed : 2015-06-25 Club Méditerranée S.A.
+clubmed
+
+// coach : 2014-10-09 Koko Island, LLC
+coach
+
+// codes : 2013-10-31 Puff Willow, LLC
+codes
+
+// coffee : 2013-10-17 Trixy Cover, LLC
+coffee
+
+// college : 2014-01-16 XYZ.COM LLC
+college
+
+// cologne : 2014-02-05 NetCologne Gesellschaft für Telekommunikation mbH
+cologne
+
+// comcast : 2015-07-23 Comcast IP Holdings I, LLC
+comcast
+
+// commbank : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA
+commbank
+
+// community : 2013-12-05 Fox Orchard, LLC
+community
+
+// company : 2013-11-07 Silver Avenue, LLC
+company
+
+// computer : 2013-10-24 Pine Mill, LLC
+computer
+
+// comsec : 2015-01-08 VeriSign, Inc.
+comsec
+
+// condos : 2013-12-05 Pine House, LLC
+condos
+
+// construction : 2013-09-16 Fox Dynamite, LLC
+construction
+
+// consulting : 2013-12-05
+consulting
+
+// contact : 2015-01-08 Top Level Spectrum, Inc.
+contact
+
+// contractors : 2013-09-10 Magic Woods, LLC
+contractors
+
+// cooking : 2013-11-21 Top Level Domain Holdings Limited
+cooking
+
+// cookingchannel : 2015-07-02 Lifestyle Domain Holdings, Inc.
+cookingchannel
+
+// cool : 2013-11-14 Koko Lake, LLC
+cool
+
+// corsica : 2014-09-25 Collectivité Territoriale de Corse
+corsica
+
+// country : 2013-12-19 Top Level Domain Holdings Limited
+country
+
+// coupon : 2015-02-26 Amazon EU S.à r.l.
+coupon
+
+// coupons : 2015-03-26 Black Island, LLC
+coupons
+
+// courses : 2014-12-04 OPEN UNIVERSITIES AUSTRALIA PTY LTD
+courses
+
+// credit : 2014-03-20 Snow Shadow, LLC
+credit
+
+// creditcard : 2014-03-20 Binky Frostbite, LLC
+creditcard
+
+// creditunion : 2015-01-22 CUNA Performance Resources, LLC
+creditunion
+
+// cricket : 2014-10-09 dot Cricket Limited
+cricket
+
+// crown : 2014-10-24 Crown Equipment Corporation
+crown
+
+// crs : 2014-04-03 Federated Co-operatives Limited
+crs
+
+// cruises : 2013-12-05 Spring Way, LLC
+cruises
+
+// csc : 2014-09-25 Alliance-One Services, Inc.
+csc
+
+// cuisinella : 2014-04-03 SALM S.A.S.
+cuisinella
+
+// cymru : 2014-05-08 Nominet UK
+cymru
+
+// cyou : 2015-01-22 Beijing Gamease Age Digital Technology Co., Ltd.
+cyou
+
+// dabur : 2014-02-06 Dabur India Limited
+dabur
+
+// dad : 2014-01-23 Charleston Road Registry Inc.
+dad
+
+// dance : 2013-10-24 United TLD Holdco Ltd.
+dance
+
+// date : 2014-11-20 dot Date Limited
+date
+
+// dating : 2013-12-05 Pine Fest, LLC
+dating
+
+// datsun : 2014-03-27 NISSAN MOTOR CO., LTD.
+datsun
+
+// day : 2014-01-30 Charleston Road Registry Inc.
+day
+
+// dclk : 2014-11-20 Charleston Road Registry Inc.
+dclk
+
+// dds : 2015-05-07 Top Level Domain Holdings Limited
+dds
+
+// deal : 2015-06-25 Amazon EU S.à r.l.
+deal
+
+// dealer : 2014-12-22 Dealer Dot Com, Inc.
+dealer
+
+// deals : 2014-05-22 Sand Sunset, LLC
+deals
+
+// degree : 2014-03-06
+degree
+
+// delivery : 2014-09-11 Steel Station, LLC
+delivery
+
+// dell : 2014-10-24 Dell Inc.
+dell
+
+// delta : 2015-02-19 Delta Air Lines, Inc.
+delta
+
+// democrat : 2013-10-24 United TLD Holdco Ltd.
+democrat
+
+// dental : 2014-03-20 Tin Birch, LLC
+dental
+
+// dentist : 2014-03-20
+dentist
+
+// desi : 2013-11-14 Desi Networks LLC
+desi
+
+// design : 2014-11-07 Top Level Design, LLC
+design
+
+// dev : 2014-10-16 Charleston Road Registry Inc.
+dev
+
+// dhl : 2015-07-23 Deutsche Post AG
+dhl
+
+// diamonds : 2013-09-22 John Edge, LLC
+diamonds
+
+// diet : 2014-06-26 Uniregistry, Corp.
+diet
+
+// digital : 2014-03-06 Dash Park, LLC
+digital
+
+// direct : 2014-04-10 Half Trail, LLC
+direct
+
+// directory : 2013-09-20 Extra Madison, LLC
+directory
+
+// discount : 2014-03-06 Holly Hill, LLC
+discount
+
+// discover : 2015-07-23 Discover Financial Services
+discover
+
+// dnp : 2013-12-13 Dai Nippon Printing Co., Ltd.
+dnp
+
+// docs : 2014-10-16 Charleston Road Registry Inc.
+docs
+
+// dog : 2014-12-04 Koko Mill, LLC
+dog
+
+// doha : 2014-09-18 Communications Regulatory Authority (CRA)
+doha
+
+// domains : 2013-10-17 Sugar Cross, LLC
+domains
+
+// doosan : 2014-04-03 Doosan Corporation
+doosan
+
+// dot : 2015-05-21 Dish DBS Corporation
+dot
+
+// download : 2014-11-20 dot Support Limited
+download
+
+// drive : 2015-03-05 Charleston Road Registry Inc.
+drive
+
+// dstv : 2015-03-12 MultiChoice (Proprietary) Limited
+dstv
+
+// dtv : 2015-06-04 Dish DBS Corporation
+dtv
+
+// dubai : 2015-01-01 Dubai Smart Government Department
+dubai
+
+// duck : 2015-07-23 Johnson Shareholdings, Inc.
+duck
+
+// dunlop : 2015-07-02 The Goodyear Tire & Rubber Company
+dunlop
+
+// dupont : 2015-06-25 E.I. du Pont de Nemours and Company
+dupont
+
+// durban : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry
+durban
+
+// dvag : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG
+dvag
+
+// dwg : 2015-07-23 Autodesk, Inc.
+dwg
+
+// earth : 2014-12-04 Interlink Co., Ltd.
+earth
+
+// eat : 2014-01-23 Charleston Road Registry Inc.
+eat
+
+// edeka : 2014-12-18 EDEKA Verband kaufmännischer Genossenschaften e.V.
+edeka
+
+// education : 2013-11-07 Brice Way, LLC
+education
+
+// email : 2013-10-31 Spring Madison, LLC
+email
+
+// emerck : 2014-04-03 Merck KGaA
+emerck
+
+// emerson : 2015-07-23 Emerson Electric Co.
+emerson
+
+// energy : 2014-09-11 Binky Birch, LLC
+energy
+
+// engineer : 2014-03-06 United TLD Holdco Ltd.
+engineer
+
+// engineering : 2014-03-06 Romeo Canyon
+engineering
+
+// enterprises : 2013-09-20 Snow Oaks, LLC
+enterprises
+
+// epost : 2015-07-23 Deutsche Post AG
+epost
+
+// epson : 2014-12-04 Seiko Epson Corporation
+epson
+
+// equipment : 2013-08-27 Corn Station, LLC
+equipment
+
+// ericsson : 2015-07-09 Telefonaktiebolaget L M Ericsson
+ericsson
+
+// erni : 2014-04-03 ERNI Group Holding AG
+erni
+
+// esq : 2014-05-08 Charleston Road Registry Inc.
+esq
+
+// estate : 2013-08-27 Trixy Park, LLC
+estate
+
+// esurance : 2015-07-23 Esurance Insurance Company
+esurance
+
+// eurovision : 2014-04-24 European Broadcasting Union (EBU)
+eurovision
+
+// eus : 2013-12-12 Puntueus Fundazioa
+eus
+
+// events : 2013-12-05 Pioneer Maple, LLC
+events
+
+// everbank : 2014-05-15 EverBank
+everbank
+
+// exchange : 2014-03-06 Spring Falls, LLC
+exchange
+
+// expert : 2013-11-21 Magic Pass, LLC
+expert
+
+// exposed : 2013-12-05 Victor Beach, LLC
+exposed
+
+// express : 2015-02-11 Sea Sunset, LLC
+express
+
+// extraspace : 2015-05-14 Extra Space Storage LLC
+extraspace
+
+// fage : 2014-12-18 Fage International S.A.
+fage
+
+// fail : 2014-03-06 Atomic Pipe, LLC
+fail
+
+// fairwinds : 2014-11-13 FairWinds Partners, LLC
+fairwinds
+
+// faith : 2014-11-20 dot Faith Limited
+faith
+
+// family : 2015-04-02
+family
+
+// fan : 2014-03-06
+fan
+
+// fans : 2014-11-07 Asiamix Digital Limited
+fans
+
+// farm : 2013-11-07 Just Maple, LLC
+farm
+
+// farmers : 2015-07-09 Farmers Insurance Exchange
+farmers
+
+// fashion : 2014-07-03 Top Level Domain Holdings Limited
+fashion
+
+// fast : 2014-12-18 Amazon EU S.à r.l.
+fast
+
+// feedback : 2013-12-19 Top Level Spectrum, Inc.
+feedback
+
+// ferrero : 2014-12-18 Ferrero Trading Lux S.A.
+ferrero
+
+// film : 2015-01-08 Motion Picture Domain Registry Pty Ltd
+film
+
+// final : 2014-10-16 Núcleo de Informação e Coordenação do Ponto BR - NIC.br
+final
+
+// finance : 2014-03-20 Cotton Cypress, LLC
+finance
+
+// financial : 2014-03-06 Just Cover, LLC
+financial
+
+// fire : 2015-06-25 Amazon EU S.à r.l.
+fire
+
+// firestone : 2014-12-18 Bridgestone Corporation
+firestone
+
+// firmdale : 2014-03-27 Firmdale Holdings Limited
+firmdale
+
+// fish : 2013-12-12 Fox Woods, LLC
+fish
+
+// fishing : 2013-11-21 Top Level Domain Holdings Limited
+fishing
+
+// fit : 2014-11-07 Top Level Domain Holdings Limited
+fit
+
+// fitness : 2014-03-06 Brice Orchard, LLC
+fitness
+
+// flickr : 2015-04-02 Yahoo! Domain Services Inc.
+flickr
+
+// flights : 2013-12-05 Fox Station, LLC
+flights
+
+// flir : 2015-07-23 FLIR Systems, Inc.
+flir
+
+// florist : 2013-11-07 Half Cypress, LLC
+florist
+
+// flowers : 2014-10-09 Uniregistry, Corp.
+flowers
+
+// flsmidth : 2014-07-24 FLSmidth A/S
+flsmidth
+
+// fly : 2014-05-08 Charleston Road Registry Inc.
+fly
+
+// foo : 2014-01-23 Charleston Road Registry Inc.
+foo
+
+// foodnetwork : 2015-07-02 Lifestyle Domain Holdings, Inc.
+foodnetwork
+
+// football : 2014-12-18 Foggy Farms, LLC
+football
+
+// ford : 2014-11-13 Ford Motor Company
+ford
+
+// forex : 2014-12-11 IG Group Holdings PLC
+forex
+
+// forsale : 2014-05-22
+forsale
+
+// forum : 2015-04-02 Fegistry, LLC
+forum
+
+// foundation : 2013-12-05 John Dale, LLC
+foundation
+
+// frl : 2014-05-15 FRLregistry B.V.
+frl
+
+// frogans : 2013-12-19 OP3FT
+frogans
+
+// frontdoor : 2015-07-02 Lifestyle Domain Holdings, Inc.
+frontdoor
+
+// frontier : 2015-02-05 Frontier Communications Corporation
+frontier
+
+// ftr : 2015-07-16 Frontier Communications Corporation
+ftr
+
+// fujixerox : 2015-07-23 Xerox DNHC LLC
+fujixerox
+
+// fund : 2014-03-20 John Castle, LLC
+fund
+
+// furniture : 2014-03-20 Lone Fields, LLC
+furniture
+
+// futbol : 2013-09-20
+futbol
+
+// fyi : 2015-04-02 Silver Tigers, LLC
+fyi
+
+// gal : 2013-11-07 Asociación puntoGAL
+gal
+
+// gallery : 2013-09-13 Sugar House, LLC
+gallery
+
+// gallo : 2015-06-11 Gallo Vineyards, Inc.
+gallo
+
+// gallup : 2015-02-19 Gallup, Inc.
+gallup
+
+// game : 2015-05-28 Uniregistry, Corp.
+game
+
+// games : 2015-05-28 Foggy Beach, LLC
+games
+
+// garden : 2014-06-26 Top Level Domain Holdings Limited
+garden
+
+// gbiz : 2014-07-17 Charleston Road Registry Inc.
+gbiz
+
+// gdn : 2014-07-31 Joint Stock Company "Navigation-information systems"
+gdn
+
+// gea : 2014-12-04 GEA Group Aktiengesellschaft
+gea
+
+// gent : 2014-01-23 COMBELL GROUP NV/SA
+gent
+
+// genting : 2015-03-12 Resorts World Inc Pte. Ltd.
+genting
+
+// ggee : 2014-01-09 GMO Internet, Inc.
+ggee
+
+// gift : 2013-10-17 Uniregistry, Corp.
+gift
+
+// gifts : 2014-07-03 Goose Sky, LLC
+gifts
+
+// gives : 2014-03-06 United TLD Holdco Ltd.
+gives
+
+// giving : 2014-11-13 Giving Limited
+giving
+
+// glade : 2015-07-23 Johnson Shareholdings, Inc.
+glade
+
+// glass : 2013-11-07 Black Cover, LLC
+glass
+
+// gle : 2014-07-24 Charleston Road Registry Inc.
+gle
+
+// global : 2014-04-17 Dot GLOBAL AS
+global
+
+// globo : 2013-12-19 Globo Comunicação e Participações S.A
+globo
+
+// gmail : 2014-05-01 Charleston Road Registry Inc.
+gmail
+
+// gmo : 2014-01-09 GMO Internet, Inc.
+gmo
+
+// gmx : 2014-04-24 1&1 Mail & Media GmbH
+gmx
+
+// godaddy : 2015-07-23 Go Daddy East, LLC
+godaddy
+
+// gold : 2015-01-22 June Edge, LLC
+gold
+
+// goldpoint : 2014-11-20 YODOBASHI CAMERA CO.,LTD.
+goldpoint
+
+// golf : 2014-12-18 Lone falls, LLC
+golf
+
+// goo : 2014-12-18 NTT Resonant Inc.
+goo
+
+// goodyear : 2015-07-02 The Goodyear Tire & Rubber Company
+goodyear
+
+// goog : 2014-11-20 Charleston Road Registry Inc.
+goog
+
+// google : 2014-07-24 Charleston Road Registry Inc.
+google
+
+// gop : 2014-01-16 Republican State Leadership Committee, Inc.
+gop
+
+// got : 2014-12-18 Amazon EU S.à r.l.
+got
+
+// gotv : 2015-03-12 MultiChoice (Proprietary) Limited
+gotv
+
+// grainger : 2015-05-07 Grainger Registry Services, LLC
+grainger
+
+// graphics : 2013-09-13 Over Madison, LLC
+graphics
+
+// gratis : 2014-03-20 Pioneer Tigers, LLC
+gratis
+
+// green : 2014-05-08 Afilias Limited
+green
+
+// gripe : 2014-03-06 Corn Sunset, LLC
+gripe
+
+// group : 2014-08-15 Romeo Town, LLC
+group
+
+// gucci : 2014-11-13 Guccio Gucci S.p.a.
+gucci
+
+// guge : 2014-08-28 Charleston Road Registry Inc.
+guge
+
+// guide : 2013-09-13 Snow Moon, LLC
+guide
+
+// guitars : 2013-11-14 Uniregistry, Corp.
+guitars
+
+// guru : 2013-08-27 Pioneer Cypress, LLC
+guru
+
+// hamburg : 2014-02-20 Hamburg Top-Level-Domain GmbH
+hamburg
+
+// hangout : 2014-11-13 Charleston Road Registry Inc.
+hangout
+
+// haus : 2013-12-05
+haus
+
+// hdfcbank : 2015-02-12 HDFC Bank Limited
+hdfcbank
+
+// health : 2015-02-11 DotHealth, LLC
+health
+
+// healthcare : 2014-06-12 Silver Glen, LLC
+healthcare
+
+// help : 2014-06-26 Uniregistry, Corp.
+help
+
+// helsinki : 2015-02-05 City of Helsinki
+helsinki
+
+// here : 2014-02-06 Charleston Road Registry Inc.
+here
+
+// hermes : 2014-07-10 HERMES INTERNATIONAL
+hermes
+
+// hgtv : 2015-07-02 Lifestyle Domain Holdings, Inc.
+hgtv
+
+// hiphop : 2014-03-06 Uniregistry, Corp.
+hiphop
+
+// hisamitsu : 2015-07-16 Hisamitsu Pharmaceutical Co.,Inc.
+hisamitsu
+
+// hitachi : 2014-10-31 Hitachi, Ltd.
+hitachi
+
+// hiv : 2014-03-13 dotHIV gemeinnuetziger e.V.
+hiv
+
+// hkt : 2015-05-14 PCCW-HKT DataCom Services Limited
+hkt
+
+// hockey : 2015-03-19 Half Willow, LLC
+hockey
+
+// holdings : 2013-08-27 John Madison, LLC
+holdings
+
+// holiday : 2013-11-07 Goose Woods, LLC
+holiday
+
+// homedepot : 2015-04-02 Homer TLC, Inc.
+homedepot
+
+// homegoods : 2015-07-16 The TJX Companies, Inc.
+homegoods
+
+// homes : 2014-01-09 DERHomes, LLC
+homes
+
+// homesense : 2015-07-16 The TJX Companies, Inc.
+homesense
+
+// honda : 2014-12-18 Honda Motor Co., Ltd.
+honda
+
+// honeywell : 2015-07-23 Honeywell GTLD LLC
+honeywell
+
+// horse : 2013-11-21 Top Level Domain Holdings Limited
+horse
+
+// host : 2014-04-17 DotHost Inc.
+host
+
+// hosting : 2014-05-29 Uniregistry, Corp.
+hosting
+
+// hoteles : 2015-03-05 Travel Reservations SRL
+hoteles
+
+// hotmail : 2014-12-18 Microsoft Corporation
+hotmail
+
+// house : 2013-11-07 Sugar Park, LLC
+house
+
+// how : 2014-01-23 Charleston Road Registry Inc.
+how
+
+// hsbc : 2014-10-24 HSBC Holdings PLC
+hsbc
+
+// htc : 2015-04-02 HTC corporation
+htc
+
+// hyundai : 2015-07-09 Hyundai Motor Company
+hyundai
+
+// ibm : 2014-07-31 International Business Machines Corporation
+ibm
+
+// icbc : 2015-02-19 Industrial and Commercial Bank of China Limited
+icbc
+
+// ice : 2014-10-30 IntercontinentalExchange, Inc.
+ice
+
+// icu : 2015-01-08 One.com A/S
+icu
+
+// ieee : 2015-07-23 IEEE Global LLC
+ieee
+
+// ifm : 2014-01-30 ifm electronic gmbh
+ifm
+
+// iinet : 2014-07-03 Connect West Pty. Ltd.
+iinet
+
+// ikano : 2015-07-09 Ikano S.A.
+ikano
+
+// imdb : 2015-06-25 Amazon EU S.à r.l.
+imdb
+
+// immo : 2014-07-10 Auburn Bloom, LLC
+immo
+
+// immobilien : 2013-11-07 United TLD Holdco Ltd.
+immobilien
+
+// industries : 2013-12-05 Outer House, LLC
+industries
+
+// infiniti : 2014-03-27 NISSAN MOTOR CO., LTD.
+infiniti
+
+// ing : 2014-01-23 Charleston Road Registry Inc.
+ing
+
+// ink : 2013-12-05 Top Level Design, LLC
+ink
+
+// institute : 2013-11-07 Outer Maple, LLC
+institute
+
+// insurance : 2015-02-19 fTLD Registry Services LLC
+insurance
+
+// insure : 2014-03-20 Pioneer Willow, LLC
+insure
+
+// international : 2013-11-07 Wild Way, LLC
+international
+
+// investments : 2014-03-20 Holly Glen, LLC
+investments
+
+// ipiranga : 2014-08-28 Ipiranga Produtos de Petroleo S.A.
+ipiranga
+
+// irish : 2014-08-07 Dot-Irish LLC
+irish
+
+// iselect : 2015-02-11 iSelect Ltd
+iselect
+
+// ist : 2014-08-28 Istanbul Metropolitan Municipality
+ist
+
+// istanbul : 2014-08-28 Istanbul Metropolitan Municipality
+istanbul
+
+// itau : 2014-10-02 Itau Unibanco Holding S.A.
+itau
+
+// itv : 2015-07-09 ITV Services Limited
+itv
+
+// iwc : 2014-06-23 Richemont DNS Inc.
+iwc
+
+// jaguar : 2014-11-13 Jaguar Land Rover Ltd
+jaguar
+
+// java : 2014-06-19 Oracle Corporation
+java
+
+// jcb : 2014-11-20 JCB Co., Ltd.
+jcb
+
+// jcp : 2015-04-23 JCP Media, Inc.
+jcp
+
+// jetzt : 2014-01-09 New TLD Company AB
+jetzt
+
+// jewelry : 2015-03-05 Wild Bloom, LLC
+jewelry
+
+// jio : 2015-04-02 Affinity Names, Inc.
+jio
+
+// jlc : 2014-12-04 Richemont DNS Inc.
+jlc
+
+// jll : 2015-04-02 Jones Lang LaSalle Incorporated
+jll
+
+// jmp : 2015-03-26 Matrix IP LLC
+jmp
+
+// jnj : 2015-06-18 Johnson & Johnson Services, Inc.
+jnj
+
+// joburg : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry
+joburg
+
+// jot : 2014-12-18 Amazon EU S.à r.l.
+jot
+
+// joy : 2014-12-18 Amazon EU S.à r.l.
+joy
+
+// jpmorgan : 2015-04-30 JPMorgan Chase & Co.
+jpmorgan
+
+// jprs : 2014-09-18 Japan Registry Services Co., Ltd.
+jprs
+
+// juegos : 2014-03-20 Uniregistry, Corp.
+juegos
+
+// kaufen : 2013-11-07 United TLD Holdco Ltd.
+kaufen
+
+// kddi : 2014-09-12 KDDI CORPORATION
+kddi
+
+// kerryhotels : 2015-04-30 Kerry Trading Co. Limited
+kerryhotels
+
+// kerrylogistics : 2015-04-09 Kerry Trading Co. Limited
+kerrylogistics
+
+// kerryproperties : 2015-04-09 Kerry Trading Co. Limited
+kerryproperties
+
+// kfh : 2014-12-04 Kuwait Finance House
+kfh
+
+// kia : 2015-07-09 KIA MOTORS CORPORATION
+kia
+
+// kim : 2013-09-23 Afilias Limited
+kim
+
+// kinder : 2014-11-07 Ferrero Trading Lux S.A.
+kinder
+
+// kindle : 2015-06-25 Amazon EU S.à r.l.
+kindle
+
+// kitchen : 2013-09-20 Just Goodbye, LLC
+kitchen
+
+// kiwi : 2013-09-20 DOT KIWI LIMITED
+kiwi
+
+// koeln : 2014-01-09 NetCologne Gesellschaft für Telekommunikation mbH
+koeln
+
+// komatsu : 2015-01-08 Komatsu Ltd.
+komatsu
+
+// kpmg : 2015-04-23 KPMG International Cooperative (KPMG International Genossenschaft)
+kpmg
+
+// kpn : 2015-01-08 Koninklijke KPN N.V.
+kpn
+
+// krd : 2013-12-05 KRG Department of Information Technology
+krd
+
+// kred : 2013-12-19 KredTLD Pty Ltd
+kred
+
+// kuokgroup : 2015-04-09 Kerry Trading Co. Limited
+kuokgroup
+
+// kyknet : 2015-03-05 Electronic Media Network (Pty) Ltd
+kyknet
+
+// kyoto : 2014-11-07 Academic Institution: Kyoto Jyoho Gakuen
+kyoto
+
+// lacaixa : 2014-01-09 CAIXA D'ESTALVIS I PENSIONS DE BARCELONA
+lacaixa
+
+// lamborghini : 2015-06-04 Automobili Lamborghini S.p.A.
+lamborghini
+
+// lancaster : 2015-02-12 LANCASTER
+lancaster
+
+// lancome : 2015-07-23 L'Oréal
+lancome
+
+// land : 2013-09-10 Pine Moon, LLC
+land
+
+// landrover : 2014-11-13 Jaguar Land Rover Ltd
+landrover
+
+// lasalle : 2015-04-02 Jones Lang LaSalle Incorporated
+lasalle
+
+// lat : 2014-10-16 ECOM-LAC Federaciòn de Latinoamèrica y el Caribe para Internet y el Comercio Electrònico
+lat
+
+// latrobe : 2014-06-16 La Trobe University
+latrobe
+
+// law : 2015-01-22 Minds + Machines Group Limited
+law
+
+// lawyer : 2014-03-20
+lawyer
+
+// lds : 2014-03-20 IRI Domain Management, LLC ("Applicant")
+lds
+
+// lease : 2014-03-06 Victor Trail, LLC
+lease
+
+// leclerc : 2014-08-07 A.C.D. LEC Association des Centres Distributeurs Edouard Leclerc
+leclerc
+
+// lefrak : 2015-07-16 LeFrak Organization, Inc.
+lefrak
+
+// legal : 2014-10-16 Blue Falls, LLC
+legal
+
+// lego : 2015-07-16 LEGO Juris A/S
+lego
+
+// lexus : 2015-04-23 TOYOTA MOTOR CORPORATION
+lexus
+
+// lgbt : 2014-05-08 Afilias Limited
+lgbt
+
+// liaison : 2014-10-02 Liaison Technologies, Incorporated
+liaison
+
+// lidl : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG
+lidl
+
+// life : 2014-02-06 Trixy Oaks, LLC
+life
+
+// lifeinsurance : 2015-01-15 American Council of Life Insurers
+lifeinsurance
+
+// lifestyle : 2014-12-11 Lifestyle Domain Holdings, Inc.
+lifestyle
+
+// lighting : 2013-08-27 John McCook, LLC
+lighting
+
+// like : 2014-12-18 Amazon EU S.à r.l.
+like
+
+// limited : 2014-03-06 Big Fest, LLC
+limited
+
+// limo : 2013-10-17 Hidden Frostbite, LLC
+limo
+
+// lincoln : 2014-11-13 Ford Motor Company
+lincoln
+
+// linde : 2014-12-04 Linde Aktiengesellschaft
+linde
+
+// link : 2013-11-14 Uniregistry, Corp.
+link
+
+// lipsy : 2015-06-25 Lipsy Ltd
+lipsy
+
+// live : 2014-12-04
+live
+
+// lixil : 2015-03-19 LIXIL Group Corporation
+lixil
+
+// loan : 2014-11-20 dot Loan Limited
+loan
+
+// loans : 2014-03-20 June Woods, LLC
+loans
+
+// locker : 2015-06-04 Dish DBS Corporation
+locker
+
+// locus : 2015-06-25 Locus Analytics LLC
+locus
+
+// lol : 2015-01-30 Uniregistry, Corp.
+lol
+
+// london : 2013-11-14 Dot London Domains Limited
+london
+
+// lotte : 2014-11-07 Lotte Holdings Co., Ltd.
+lotte
+
+// lotto : 2014-04-10 Afilias Limited
+lotto
+
+// love : 2014-12-22 Merchant Law Group LLP
+love
+
+// ltd : 2014-09-25 Over Corner, LLC
+ltd
+
+// ltda : 2014-04-17 DOMAIN ROBOT SERVICOS DE HOSPEDAGEM NA INTERNET LTDA
+ltda
+
+// lupin : 2014-11-07 LUPIN LIMITED
+lupin
+
+// luxe : 2014-01-09 Top Level Domain Holdings Limited
+luxe
+
+// luxury : 2013-10-17 Luxury Partners, LLC
+luxury
+
+// madrid : 2014-05-01 Comunidad de Madrid
+madrid
+
+// maif : 2014-10-02 Mutuelle Assurance Instituteur France (MAIF)
+maif
+
+// maison : 2013-12-05 Victor Frostbite, LLC
+maison
+
+// makeup : 2015-01-15 L'Oréal
+makeup
+
+// man : 2014-12-04 MAN SE
+man
+
+// management : 2013-11-07 John Goodbye, LLC
+management
+
+// mango : 2013-10-24 PUNTO FA S.L.
+mango
+
+// market : 2014-03-06
+market
+
+// marketing : 2013-11-07 Fern Pass, LLC
+marketing
+
+// markets : 2014-12-11 IG Group Holdings PLC
+markets
+
+// marriott : 2014-10-09 Marriott Worldwide Corporation
+marriott
+
+// marshalls : 2015-07-16 The TJX Companies, Inc.
+marshalls
+
+// mba : 2015-04-02 Lone Hollow, LLC
+mba
+
+// media : 2014-03-06 Grand Glen, LLC
+media
+
+// meet : 2014-01-16
+meet
+
+// melbourne : 2014-05-29 The Crown in right of the State of Victoria, represented by its Department of State Development, Business and Innovation
+melbourne
+
+// meme : 2014-01-30 Charleston Road Registry Inc.
+meme
+
+// memorial : 2014-10-16 Dog Beach, LLC
+memorial
+
+// men : 2015-02-26 Exclusive Registry Limited
+men
+
+// menu : 2013-09-11 Wedding TLD2, LLC
+menu
+
+// meo : 2014-11-07 PT Comunicacoes S.A.
+meo
+
+// metlife : 2015-05-07 MetLife Services and Solutions, LLC
+metlife
+
+// miami : 2013-12-19 Top Level Domain Holdings Limited
+miami
+
+// microsoft : 2014-12-18 Microsoft Corporation
+microsoft
+
+// mini : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft
+mini
+
+// mit : 2015-07-02 Massachusetts Institute of Technology
+mit
+
+// mitsubishi : 2015-07-23 Mitsubishi Corporation
+mitsubishi
+
+// mlb : 2015-05-21 MLB Advanced Media DH, LLC
+mlb
+
+// mls : 2015-04-23 The Canadian Real Estate Association
+mls
+
+// mma : 2014-11-07 MMA IARD
+mma
+
+// mnet : 2015-03-05 Electronic Media Network (Pty) Ltd
+mnet
+
+// mobily : 2014-12-18 GreenTech Consultancy Company W.L.L.
+mobily
+
+// moda : 2013-11-07 United TLD Holdco Ltd.
+moda
+
+// moe : 2013-11-13 Interlink Co., Ltd.
+moe
+
+// moi : 2014-12-18 Amazon EU S.à r.l.
+moi
+
+// mom : 2015-04-16 Uniregistry, Corp.
+mom
+
+// monash : 2013-09-30 Monash University
+monash
+
+// money : 2014-10-16 Outer McCook, LLC
+money
+
+// montblanc : 2014-06-23 Richemont DNS Inc.
+montblanc
+
+// mormon : 2013-12-05 IRI Domain Management, LLC ("Applicant")
+mormon
+
+// mortgage : 2014-03-20
+mortgage
+
+// moscow : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID)
+moscow
+
+// moto : 2015-06-04 Charleston Road Registry Inc.
+moto
+
+// motorcycles : 2014-01-09 DERMotorcycles, LLC
+motorcycles
+
+// mov : 2014-01-30 Charleston Road Registry Inc.
+mov
+
+// movie : 2015-02-05 New Frostbite, LLC
+movie
+
+// movistar : 2014-10-16 Telefónica S.A.
+movistar
+
+// msd : 2015-07-23 MSD Registry Holdings, Inc.
+msd
+
+// mtn : 2014-12-04 MTN Dubai Limited
+mtn
+
+// mtpc : 2014-11-20 Mitsubishi Tanabe Pharma Corporation
+mtpc
+
+// mtr : 2015-03-12 MTR Corporation Limited
+mtr
+
+// multichoice : 2015-03-12 MultiChoice (Proprietary) Limited
+multichoice
+
+// mutual : 2015-04-02 Northwestern Mutual MU TLD Registry, LLC
+mutual
+
+// mutuelle : 2015-06-18 Fédération Nationale de la Mutualité Française
+mutuelle
+
+// mzansimagic : 2015-03-05 Electronic Media Network (Pty) Ltd
+mzansimagic
+
+// nadex : 2014-12-11 IG Group Holdings PLC
+nadex
+
+// nagoya : 2013-10-24 GMO Registry, Inc.
+nagoya
+
+// naspers : 2015-02-12 Intelprop (Proprietary) Limited
+naspers
+
+// nationwide : 2015-07-23 Nationwide Mutual Insurance Company
+nationwide
+
+// natura : 2015-03-12 NATURA COSMÉTICOS S.A.
+natura
+
+// navy : 2014-03-06 United TLD Holdco Ltd.
+navy
+
+// nec : 2015-01-08 NEC Corporation
+nec
+
+// netbank : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA
+netbank
+
+// netflix : 2015-06-18 Netflix, Inc.
+netflix
+
+// network : 2013-11-14 Trixy Manor, LLC
+network
+
+// neustar : 2013-12-05 NeuStar, Inc.
+neustar
+
+// new : 2014-01-30 Charleston Road Registry Inc.
+new
+
+// news : 2014-12-18
+news
+
+// next : 2015-06-18 Next plc
+next
+
+// nextdirect : 2015-06-18 Next plc
+nextdirect
+
+// nexus : 2014-07-24 Charleston Road Registry Inc.
+nexus
+
+// nfl : 2015-07-23 NFL Reg Ops LLC
+nfl
+
+// ngo : 2014-03-06 Public Interest Registry
+ngo
+
+// nhk : 2014-02-13 Japan Broadcasting Corporation (NHK)
+nhk
+
+// nico : 2014-12-04 DWANGO Co., Ltd.
+nico
+
+// nike : 2015-07-23 NIKE, Inc.
+nike
+
+// nikon : 2015-05-21 NIKON CORPORATION
+nikon
+
+// ninja : 2013-11-07 United TLD Holdco Ltd.
+ninja
+
+// nissan : 2014-03-27 NISSAN MOTOR CO., LTD.
+nissan
+
+// nokia : 2015-01-08 Nokia Corporation
+nokia
+
+// northwesternmutual : 2015-06-18 Northwestern Mutual Registry, LLC
+northwesternmutual
+
+// norton : 2014-12-04 Symantec Corporation
+norton
+
+// now : 2015-06-25 Amazon EU S.à r.l.
+now
+
+// nowruz : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
+nowruz
+
+// nowtv : 2015-05-14 Starbucks (HK) Limited
+nowtv
+
+// nra : 2014-05-22 NRA Holdings Company, INC.
+nra
+
+// nrw : 2013-11-21 Minds + Machines GmbH
+nrw
+
+// ntt : 2014-10-31 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
+ntt
+
+// nyc : 2014-01-23 The City of New York by and through the New York City Department of Information Technology & Telecommunications
+nyc
+
+// obi : 2014-09-25 OBI Group Holding SE & Co. KGaA
+obi
+
+// observer : 2015-04-30 Guardian News and Media Limited
+observer
+
+// off : 2015-07-23 Johnson Shareholdings, Inc.
+off
+
+// office : 2015-03-12 Microsoft Corporation
+office
+
+// okinawa : 2013-12-05 BusinessRalliart Inc.
+okinawa
+
+// olayan : 2015-05-14 Crescent Holding GmbH
+olayan
+
+// olayangroup : 2015-05-14 Crescent Holding GmbH
+olayangroup
+
+// ollo : 2015-06-04 Dish DBS Corporation
+ollo
+
+// omega : 2015-01-08 The Swatch Group Ltd
+omega
+
+// one : 2014-11-07 One.com A/S
+one
+
+// ong : 2014-03-06 Public Interest Registry
+ong
+
+// onl : 2013-09-16 I-Registry Ltd.
+onl
+
+// online : 2015-01-15 DotOnline Inc.
+online
+
+// onyourside : 2015-07-23 Nationwide Mutual Insurance Company
+onyourside
+
+// ooo : 2014-01-09 INFIBEAM INCORPORATION LIMITED
+ooo
+
+// oracle : 2014-06-19 Oracle Corporation
+oracle
+
+// orange : 2015-03-12 Orange Brand Services Limited
+orange
+
+// organic : 2014-03-27 Afilias Limited
+organic
+
+// orientexpress : 2015-02-05 Belmond Ltd.
+orientexpress
+
+// osaka : 2014-09-04 Interlink Co., Ltd.
+osaka
+
+// otsuka : 2013-10-11 Otsuka Holdings Co., Ltd.
+otsuka
+
+// ott : 2015-06-04 Dish DBS Corporation
+ott
+
+// ovh : 2014-01-16 OVH SAS
+ovh
+
+// page : 2014-12-04 Charleston Road Registry Inc.
+page
+
+// pamperedchef : 2015-02-05 The Pampered Chef, Ltd.
+pamperedchef
+
+// panerai : 2014-11-07 Richemont DNS Inc.
+panerai
+
+// paris : 2014-01-30 City of Paris
+paris
+
+// pars : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
+pars
+
+// partners : 2013-12-05 Magic Glen, LLC
+partners
+
+// parts : 2013-12-05 Sea Goodbye, LLC
+parts
+
+// party : 2014-09-11 Blue Sky Registry Limited
+party
+
+// passagens : 2015-03-05 Travel Reservations SRL
+passagens
+
+// payu : 2015-02-12 MIH PayU B.V.
+payu
+
+// pccw : 2015-05-14 PCCW Enterprises Limited
+pccw
+
+// pet : 2015-05-07 Afilias plc
+pet
+
+// pharmacy : 2014-06-19 National Association of Boards of Pharmacy
+pharmacy
+
+// philips : 2014-11-07 Koninklijke Philips N.V.
+philips
+
+// photo : 2013-11-14 Uniregistry, Corp.
+photo
+
+// photography : 2013-09-20 Sugar Glen, LLC
+photography
+
+// photos : 2013-10-17 Sea Corner, LLC
+photos
+
+// physio : 2014-05-01 PhysBiz Pty Ltd
+physio
+
+// piaget : 2014-10-16 Richemont DNS Inc.
+piaget
+
+// pics : 2013-11-14 Uniregistry, Corp.
+pics
+
+// pictet : 2014-06-26 Pictet Europe S.A.
+pictet
+
+// pictures : 2014-03-06 Foggy Sky, LLC
+pictures
+
+// pid : 2015-01-08 Top Level Spectrum, Inc.
+pid
+
+// pin : 2014-12-18 Amazon EU S.à r.l.
+pin
+
+// ping : 2015-06-11 Ping Registry Provider, Inc.
+ping
+
+// pink : 2013-10-01 Afilias Limited
+pink
+
+// pioneer : 2015-07-16 Pioneer Corporation
+pioneer
+
+// pizza : 2014-06-26 Foggy Moon, LLC
+pizza
+
+// place : 2014-04-24 Snow Galley, LLC
+place
+
+// play : 2015-03-05 Charleston Road Registry Inc.
+play
+
+// playstation : 2015-07-02 Sony Computer Entertainment Inc.
+playstation
+
+// plumbing : 2013-09-10 Spring Tigers, LLC
+plumbing
+
+// plus : 2015-02-05 Sugar Mill, LLC
+plus
+
+// pnc : 2015-07-02 PNC Domain Co., LLC
+pnc
+
+// pohl : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG
+pohl
+
+// poker : 2014-07-03 Afilias Domains No. 5 Limited
+poker
+
+// porn : 2014-10-16 ICM Registry PN LLC
+porn
+
+// praxi : 2013-12-05 Praxi S.p.A.
+praxi
+
+// press : 2014-04-03 DotPress Inc.
+press
+
+// prime : 2015-06-25 Amazon EU S.à r.l.
+prime
+
+// prod : 2014-01-23 Charleston Road Registry Inc.
+prod
+
+// productions : 2013-12-05 Magic Birch, LLC
+productions
+
+// prof : 2014-07-24 Charleston Road Registry Inc.
+prof
+
+// progressive : 2015-07-23 Progressive Casualty Insurance Company
+progressive
+
+// promo : 2014-12-18 Play.PROMO Oy
+promo
+
+// properties : 2013-12-05 Big Pass, LLC
+properties
+
+// property : 2014-05-22 Uniregistry, Corp.
+property
+
+// protection : 2015-04-23
+protection
+
+// pub : 2013-12-12 United TLD Holdco Ltd.
+pub
+
+// qpon : 2013-11-14 dotCOOL, Inc.
+qpon
+
+// quebec : 2013-12-19 PointQuébec Inc
+quebec
+
+// quest : 2015-03-26 Quest ION Limited
+quest
+
+// racing : 2014-12-04 Premier Registry Limited
+racing
+
+// raid : 2015-07-23 Johnson Shareholdings, Inc.
+raid
+
+// read : 2014-12-18 Amazon EU S.à r.l.
+read
+
+// realtor : 2014-05-29 Real Estate Domains LLC
+realtor
+
+// realty : 2015-03-19 Fegistry, LLC
+realty
+
+// recipes : 2013-10-17 Grand Island, LLC
+recipes
+
+// red : 2013-11-07 Afilias Limited
+red
+
+// redstone : 2014-10-31 Redstone Haute Couture Co., Ltd.
+redstone
+
+// redumbrella : 2015-03-26 Travelers TLD, LLC
+redumbrella
+
+// rehab : 2014-03-06 United TLD Holdco Ltd.
+rehab
+
+// reise : 2014-03-13
+reise
+
+// reisen : 2014-03-06 New Cypress, LLC
+reisen
+
+// reit : 2014-09-04 National Association of Real Estate Investment Trusts, Inc.
+reit
+
+// reliance : 2015-04-02 Reliance Industries Limited
+reliance
+
+// ren : 2013-12-12 Beijing Qianxiang Wangjing Technology Development Co., Ltd.
+ren
+
+// rent : 2014-12-04 DERRent, LLC
+rent
+
+// rentals : 2013-12-05 Big Hollow,LLC
+rentals
+
+// repair : 2013-11-07 Lone Sunset, LLC
+repair
+
+// report : 2013-12-05 Binky Glen, LLC
+report
+
+// republican : 2014-03-20 United TLD Holdco Ltd.
+republican
+
+// rest : 2013-12-19 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable
+rest
+
+// restaurant : 2014-07-03 Snow Avenue, LLC
+restaurant
+
+// review : 2014-11-20 dot Review Limited
+review
+
+// reviews : 2013-09-13
+reviews
+
+// rexroth : 2015-06-18 Robert Bosch GMBH
+rexroth
+
+// rich : 2013-11-21 I-Registry Ltd.
+rich
+
+// richardli : 2015-05-14 Pacific Century Asset Management (HK) Limited
+richardli
+
+// ricoh : 2014-11-20 Ricoh Company, Ltd.
+ricoh
+
+// rightathome : 2015-07-23 Johnson Shareholdings, Inc.
+rightathome
+
+// ril : 2015-04-02 Reliance Industries Limited
+ril
+
+// rio : 2014-02-27 Empresa Municipal de Informática SA - IPLANRIO
+rio
+
+// rip : 2014-07-10 United TLD Holdco Ltd.
+rip
+
+// rocher : 2014-12-18 Ferrero Trading Lux S.A.
+rocher
+
+// rocks : 2013-11-14
+rocks
+
+// rodeo : 2013-12-19 Top Level Domain Holdings Limited
+rodeo
+
+// room : 2014-12-18 Amazon EU S.à r.l.
+room
+
+// rsvp : 2014-05-08 Charleston Road Registry Inc.
+rsvp
+
+// ruhr : 2013-10-02 regiodot GmbH & Co. KG
+ruhr
+
+// run : 2015-03-19 Snow Park, LLC
+run
+
+// rwe : 2015-04-02 RWE AG
+rwe
+
+// ryukyu : 2014-01-09 BusinessRalliart Inc.
+ryukyu
+
+// saarland : 2013-12-12 dotSaarland GmbH
+saarland
+
+// safe : 2014-12-18 Amazon EU S.à r.l.
+safe
+
+// safety : 2015-01-08 Safety Registry Services, LLC.
+safety
+
+// sakura : 2014-12-18 SAKURA Internet Inc.
+sakura
+
+// sale : 2014-10-16
+sale
+
+// salon : 2014-12-11 Outer Orchard, LLC
+salon
+
+// samsung : 2014-04-03 SAMSUNG SDS CO., LTD
+samsung
+
+// sandvik : 2014-11-13 Sandvik AB
+sandvik
+
+// sandvikcoromant : 2014-11-07 Sandvik AB
+sandvikcoromant
+
+// sanofi : 2014-10-09 Sanofi
+sanofi
+
+// sap : 2014-03-27 SAP AG
+sap
+
+// sapo : 2014-11-07 PT Comunicacoes S.A.
+sapo
+
+// sarl : 2014-07-03 Delta Orchard, LLC
+sarl
+
+// sas : 2015-04-02 Research IP LLC
+sas
+
+// save : 2015-06-25 Amazon EU S.à r.l.
+save
+
+// saxo : 2014-10-31 Saxo Bank A/S
+saxo
+
+// sbi : 2015-03-12 STATE BANK OF INDIA
+sbi
+
+// sbs : 2014-11-07 SPECIAL BROADCASTING SERVICE CORPORATION
+sbs
+
+// sca : 2014-03-13 SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ)
+sca
+
+// scb : 2014-02-20 The Siam Commercial Bank Public Company Limited ("SCB")
+scb
+
+// schmidt : 2014-04-03 SALM S.A.S.
+schmidt
+
+// scholarships : 2014-04-24 Scholarships.com, LLC
+scholarships
+
+// school : 2014-12-18 Little Galley, LLC
+school
+
+// schule : 2014-03-06 Outer Moon, LLC
+schule
+
+// schwarz : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG
+schwarz
+
+// science : 2014-09-11 dot Science Limited
+science
+
+// scjohnson : 2015-07-23 Johnson Shareholdings, Inc.
+scjohnson
+
+// scor : 2014-10-31 SCOR SE
+scor
+
+// scot : 2014-01-23 Dot Scot Registry Limited
+scot
+
+// seat : 2014-05-22 SEAT, S.A. (Sociedad Unipersonal)
+seat
+
+// security : 2015-05-14
+security
+
+// seek : 2014-12-04 Seek Limited
+seek
+
+// sener : 2014-10-24 Sener Ingeniería y Sistemas, S.A.
+sener
+
+// services : 2014-02-27 Fox Castle, LLC
+services
+
+// ses : 2015-07-23 SES
+ses
+
+// sew : 2014-07-17 SEW-EURODRIVE GmbH & Co KG
+sew
+
+// sex : 2014-11-13 ICM Registry SX LLC
+sex
+
+// sexy : 2013-09-11 Uniregistry, Corp.
+sexy
+
+// sharp : 2014-05-01 Sharp Corporation
+sharp
+
+// shaw : 2015-04-23 Shaw Cablesystems G.P.
+shaw
+
+// shia : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
+shia
+
+// shiksha : 2013-11-14 Afilias Limited
+shiksha
+
+// shoes : 2013-10-02 Binky Galley, LLC
+shoes
+
+// shouji : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD.
+shouji
+
+// show : 2015-03-05 Snow Beach, LLC
+show
+
+// shriram : 2014-01-23 Shriram Capital Ltd.
+shriram
+
+// silk : 2015-06-25 Amazon EU S.à r.l.
+silk
+
+// sina : 2015-03-12 Sina Corporation
+sina
+
+// singles : 2013-08-27 Fern Madison, LLC
+singles
+
+// site : 2015-01-15 DotSite Inc.
+site
+
+// ski : 2015-04-09 STARTING DOT LIMITED
+ski
+
+// skin : 2015-01-15 L'Oréal
+skin
+
+// sky : 2014-06-19 Sky IP International Ltd, a company incorporated in England and Wales, operating via its registered Swiss branch
+sky
+
+// skype : 2014-12-18 Microsoft Corporation
+skype
+
+// smart : 2015-07-09 Smart Communications, Inc. (SMART)
+smart
+
+// smile : 2014-12-18 Amazon EU S.à r.l.
+smile
+
+// sncf : 2015-02-19 Société Nationale des Chemins de fer Francais S N C F
+sncf
+
+// soccer : 2015-03-26 Foggy Shadow, LLC
+soccer
+
+// social : 2013-11-07 United TLD Holdco Ltd.
+social
+
+// softbank : 2015-07-02 SoftBank Corp.
+softbank
+
+// software : 2014-03-20
+software
+
+// sohu : 2013-12-19 Sohu.com Limited
+sohu
+
+// solar : 2013-11-07 Ruby Town, LLC
+solar
+
+// solutions : 2013-11-07 Silver Cover, LLC
+solutions
+
+// song : 2015-02-26 Amazon EU S.à r.l.
+song
+
+// sony : 2015-01-08 Sony Corporation
+sony
+
+// soy : 2014-01-23 Charleston Road Registry Inc.
+soy
+
+// space : 2014-04-03 DotSpace Inc.
+space
+
+// spiegel : 2014-02-05 SPIEGEL-Verlag Rudolf Augstein GmbH & Co. KG
+spiegel
+
+// spot : 2015-02-26 Amazon EU S.à r.l.
+spot
+
+// spreadbetting : 2014-12-11 IG Group Holdings PLC
+spreadbetting
+
+// srl : 2015-05-07 mySRL GmbH
+srl
+
+// stada : 2014-11-13 STADA Arzneimittel AG
+stada
+
+// star : 2015-01-08 Star India Private Limited
+star
+
+// starhub : 2015-02-05 StarHub Limited
+starhub
+
+// statebank : 2015-03-12 STATE BANK OF INDIA
+statebank
+
+// statoil : 2014-12-04 Statoil ASA
+statoil
+
+// stc : 2014-10-09 Saudi Telecom Company
+stc
+
+// stcgroup : 2014-10-09 Saudi Telecom Company
+stcgroup
+
+// stockholm : 2014-12-18 Stockholms kommun
+stockholm
+
+// storage : 2014-12-22 Self Storage Company LLC
+storage
+
+// store : 2015-04-09 DotStore Inc.
+store
+
+// studio : 2015-02-11
+studio
+
+// study : 2014-12-11 OPEN UNIVERSITIES AUSTRALIA PTY LTD
+study
+
+// style : 2014-12-04 Binky Moon, LLC
+style
+
+// sucks : 2014-12-22 Vox Populi Registry Inc.
+sucks
+
+// supersport : 2015-03-05 SuperSport International Holdings Proprietary Limited
+supersport
+
+// supplies : 2013-12-19 Atomic Fields, LLC
+supplies
+
+// supply : 2013-12-19 Half Falls, LLC
+supply
+
+// support : 2013-10-24 Grand Orchard, LLC
+support
+
+// surf : 2014-01-09 Top Level Domain Holdings Limited
+surf
+
+// surgery : 2014-03-20 Tin Avenue, LLC
+surgery
+
+// suzuki : 2014-02-20 SUZUKI MOTOR CORPORATION
+suzuki
+
+// swatch : 2015-01-08 The Swatch Group Ltd
+swatch
+
+// swiftcover : 2015-07-23 Swiftcover Insurance Services Limited
+swiftcover
+
+// swiss : 2014-10-16 Swiss Confederation
+swiss
+
+// sydney : 2014-09-18 State of New South Wales, Department of Premier and Cabinet
+sydney
+
+// symantec : 2014-12-04 Symantec Corporation
+symantec
+
+// systems : 2013-11-07 Dash Cypress, LLC
+systems
+
+// tab : 2014-12-04 Tabcorp Holdings Limited
+tab
+
+// taipei : 2014-07-10 Taipei City Government
+taipei
+
+// talk : 2015-04-09 Amazon EU S.à r.l.
+talk
+
+// taobao : 2015-01-15 Alibaba Group Holding Limited
+taobao
+
+// tatamotors : 2015-03-12 Tata Motors Ltd
+tatamotors
+
+// tatar : 2014-04-24 Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic"
+tatar
+
+// tattoo : 2013-08-30 Uniregistry, Corp.
+tattoo
+
+// tax : 2014-03-20 Storm Orchard, LLC
+tax
+
+// taxi : 2015-03-19 Pine Falls, LLC
+taxi
+
+// tci : 2014-09-12 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
+tci
+
+// tdk : 2015-06-11 TDK Corporation
+tdk
+
+// team : 2015-03-05 Atomic Lake, LLC
+team
+
+// tech : 2015-01-30 Dot Tech LLC
+tech
+
+// technology : 2013-09-13 Auburn Falls
+technology
+
+// telecity : 2015-02-19 TelecityGroup International Limited
+telecity
+
+// telefonica : 2014-10-16 Telefónica S.A.
+telefonica
+
+// temasek : 2014-08-07 Temasek Holdings (Private) Limited
+temasek
+
+// tennis : 2014-12-04 Cotton Bloom, LLC
+tennis
+
+// teva : 2015-07-02 Teva Pharmaceutical Industries Limited
+teva
+
+// thd : 2015-04-02 Homer TLC, Inc.
+thd
+
+// theater : 2015-03-19 Blue Tigers, LLC
+theater
+
+// theatre : 2015-05-07
+theatre
+
+// theguardian : 2015-04-30 Guardian News and Media Limited
+theguardian
+
+// tiaa : 2015-07-23 Teachers Insurance and Annuity Association of America
+tiaa
+
+// tickets : 2015-02-05 Accent Media Limited
+tickets
+
+// tienda : 2013-11-14 Victor Manor, LLC
+tienda
+
+// tiffany : 2015-01-30 Tiffany and Company
+tiffany
+
+// tips : 2013-09-20 Corn Willow, LLC
+tips
+
+// tires : 2014-11-07 Dog Edge, LLC
+tires
+
+// tirol : 2014-04-24 punkt Tirol GmbH
+tirol
+
+// tjmaxx : 2015-07-16 The TJX Companies, Inc.
+tjmaxx
+
+// tjx : 2015-07-16 The TJX Companies, Inc.
+tjx
+
+// tkmaxx : 2015-07-16 The TJX Companies, Inc.
+tkmaxx
+
+// tmall : 2015-01-15 Alibaba Group Holding Limited
+tmall
+
+// today : 2013-09-20 Pearl Woods, LLC
+today
+
+// tokyo : 2013-11-13 GMO Registry, Inc.
+tokyo
+
+// tools : 2013-11-21 Pioneer North, LLC
+tools
+
+// top : 2014-03-20 Jiangsu Bangning Science & Technology Co.,Ltd.
+top
+
+// toray : 2014-12-18 Toray Industries, Inc.
+toray
+
+// toshiba : 2014-04-10 TOSHIBA Corporation
+toshiba
+
+// tours : 2015-01-22 Sugar Station, LLC
+tours
+
+// town : 2014-03-06 Koko Moon, LLC
+town
+
+// toyota : 2015-04-23 TOYOTA MOTOR CORPORATION
+toyota
+
+// toys : 2014-03-06 Pioneer Orchard, LLC
+toys
+
+// trade : 2014-01-23 Elite Registry Limited
+trade
+
+// trading : 2014-12-11 IG Group Holdings PLC
+trading
+
+// training : 2013-11-07 Wild Willow, LLC
+training
+
+// travelchannel : 2015-07-02 Lifestyle Domain Holdings, Inc.
+travelchannel
+
+// travelers : 2015-03-26 Travelers TLD, LLC
+travelers
+
+// travelersinsurance : 2015-03-26 Travelers TLD, LLC
+travelersinsurance
+
+// trust : 2014-10-16
+trust
+
+// trv : 2015-03-26 Travelers TLD, LLC
+trv
+
+// tube : 2015-06-11 Latin American Telecom LLC
+tube
+
+// tui : 2014-07-03 TUI AG
+tui
+
+// tunes : 2015-02-26 Amazon EU S.à r.l.
+tunes
+
+// tushu : 2014-12-18 Amazon EU S.à r.l.
+tushu
+
+// tvs : 2015-02-19 T V SUNDRAM IYENGAR & SONS LIMITED
+tvs
+
+// ubs : 2014-12-11 UBS AG
+ubs
+
+// university : 2014-03-06 Little Station, LLC
+university
+
+// uno : 2013-09-11 Dot Latin LLC
+uno
+
+// uol : 2014-05-01 UBN INTERNET LTDA.
+uol
+
+// ups : 2015-06-25 UPS Market Driver, Inc.
+ups
+
+// vacations : 2013-12-05 Atomic Tigers, LLC
+vacations
+
+// vana : 2014-12-11 Lifestyle Domain Holdings, Inc.
+vana
+
+// vegas : 2014-01-16 Dot Vegas, Inc.
+vegas
+
+// ventures : 2013-08-27 Binky Lake, LLC
+ventures
+
+// versicherung : 2014-03-20 dotversicherung-registry GmbH
+versicherung
+
+// vet : 2014-03-06
+vet
+
+// viajes : 2013-10-17 Black Madison, LLC
+viajes
+
+// video : 2014-10-16
+video
+
+// vig : 2015-05-14 VIENNA INSURANCE GROUP AG Wiener Versicherung Gruppe
+vig
+
+// viking : 2015-04-02 Viking River Cruises (Bermuda) Ltd.
+viking
+
+// villas : 2013-12-05 New Sky, LLC
+villas
+
+// vin : 2015-06-18 Holly Shadow, LLC
+vin
+
+// vip : 2015-01-22 Minds + Machines Group Limited
+vip
+
+// virgin : 2014-09-25 Virgin Enterprises Limited
+virgin
+
+// vision : 2013-12-05 Koko Station, LLC
+vision
+
+// vista : 2014-09-18 Vistaprint Limited
+vista
+
+// vistaprint : 2014-09-18 Vistaprint Limited
+vistaprint
+
+// viva : 2014-11-07 Saudi Telecom Company
+viva
+
+// vlaanderen : 2014-02-06 DNS.be vzw
+vlaanderen
+
+// vodka : 2013-12-19 Top Level Domain Holdings Limited
+vodka
+
+// volkswagen : 2015-05-14 Volkswagen Group of America Inc.
+volkswagen
+
+// vote : 2013-11-21 Monolith Registry LLC
+vote
+
+// voting : 2013-11-13 Valuetainment Corp.
+voting
+
+// voto : 2013-11-21 Monolith Registry LLC
+voto
+
+// voyage : 2013-08-27 Ruby House, LLC
+voyage
+
+// vuelos : 2015-03-05 Travel Reservations SRL
+vuelos
+
+// wales : 2014-05-08 Nominet UK
+wales
+
+// walter : 2014-11-13 Sandvik AB
+walter
+
+// wang : 2013-10-24 Zodiac Leo Limited
+wang
+
+// wanggou : 2014-12-18 Amazon EU S.à r.l.
+wanggou
+
+// warman : 2015-06-18 Weir Group IP Limited
+warman
+
+// watch : 2013-11-14 Sand Shadow, LLC
+watch
+
+// watches : 2014-12-22 Richemont DNS Inc.
+watches
+
+// weather : 2015-01-08 The Weather Channel, LLC
+weather
+
+// weatherchannel : 2015-03-12 The Weather Channel, LLC
+weatherchannel
+
+// webcam : 2014-01-23 dot Webcam Limited
+webcam
+
+// weber : 2015-06-04 Saint-Gobain Weber SA
+weber
+
+// website : 2014-04-03 DotWebsite Inc.
+website
+
+// wed : 2013-10-01 Atgron, Inc.
+wed
+
+// wedding : 2014-04-24 Top Level Domain Holdings Limited
+wedding
+
+// weibo : 2015-03-05 Sina Corporation
+weibo
+
+// weir : 2015-01-29 Weir Group IP Limited
+weir
+
+// whoswho : 2014-02-20 Who's Who Registry
+whoswho
+
+// wien : 2013-10-28 punkt.wien GmbH
+wien
+
+// wiki : 2013-11-07 Top Level Design, LLC
+wiki
+
+// williamhill : 2014-03-13 William Hill Organization Limited
+williamhill
+
+// win : 2014-11-20 First Registry Limited
+win
+
+// windows : 2014-12-18 Microsoft Corporation
+windows
+
+// wine : 2015-06-18 June Station, LLC
+wine
+
+// winners : 2015-07-16 The TJX Companies, Inc.
+winners
+
+// wme : 2014-02-13 William Morris Endeavor Entertainment, LLC
+wme
+
+// woodside : 2015-07-09 Woodside Petroleum Limited
+woodside
+
+// work : 2013-12-19 Top Level Domain Holdings Limited
+work
+
+// works : 2013-11-14 Little Dynamite, LLC
+works
+
+// world : 2014-06-12 Bitter Fields, LLC
+world
+
+// wtc : 2013-12-19 World Trade Centers Association, Inc.
+wtc
+
+// wtf : 2014-03-06 Hidden Way, LLC
+wtf
+
+// xbox : 2014-12-18 Microsoft Corporation
+xbox
+
+// xerox : 2014-10-24 Xerox DNHC LLC
+xerox
+
+// xfinity : 2015-07-09 Comcast IP Holdings I, LLC
+xfinity
+
+// xihuan : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD.
+xihuan
+
+// xin : 2014-12-11 Elegant Leader Limited
+xin
+
+// xn--11b4c3d : 2015-01-15 VeriSign Sarl
+कॉम
+
+// xn--1ck2e1b : 2015-02-26 Amazon EU S.à r.l.
+セール
+
+// xn--1qqw23a : 2014-01-09 Guangzhou YU Wei Information Technology Co., Ltd.
+佛山
+
+// xn--30rr7y : 2014-06-12 Excellent First Limited
+慈善
+
+// xn--3bst00m : 2013-09-13 Eagle Horizon Limited
+集团
+
+// xn--3ds443g : 2013-09-08 TLD REGISTRY LIMITED
+在线
+
+// xn--3oq18vl8pn36a : 2015-07-02 Volkswagen (China) Investment Co., Ltd.
+大众汽车
+
+// xn--3pxu8k : 2015-01-15 VeriSign Sarl
+点看
+
+// xn--42c2d9a : 2015-01-15 VeriSign Sarl
+คอม
+
+// xn--45q11c : 2013-11-21 Zodiac Scorpio Limited
+八卦
+
+// xn--4gbrim : 2013-10-04 Suhub Electronic Establishment
+موقع
+
+// xn--55qw42g : 2013-11-08 China Organizational Name Administration Center
+公益
+
+// xn--55qx5d : 2013-11-14 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center)
+公司
+
+// xn--5tzm5g : 2014-12-22 Global Website TLD Asia Limited
+网站
+
+// xn--6frz82g : 2013-09-23 Afilias Limited
+移动
+
+// xn--6qq986b3xl : 2013-09-13 Tycoon Treasure Limited
+我爱你
+
+// xn--80adxhks : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID)
+москва
+
+// xn--80asehdb : 2013-07-14 CORE Association
+онлайн
+
+// xn--80aswg : 2013-07-14 CORE Association
+сайт
+
+// xn--8y0a063a : 2015-03-26 China United Network Communications Corporation Limited
+联通
+
+// xn--9dbq2a : 2015-01-15 VeriSign Sarl
+קום
+
+// xn--9et52u : 2014-06-12 RISE VICTORY LIMITED
+时尚
+
+// xn--9krt00a : 2015-03-12 Sina Corporation
+微博
+
+// xn--b4w605ferd : 2014-08-07 Temasek Holdings (Private) Limited
+淡马锡
+
+// xn--bck1b9a5dre4c : 2015-02-26 Amazon EU S.à r.l.
+ファッション
+
+// xn--c1avg : 2013-11-14 Public Interest Registry
+орг
+
+// xn--c2br7g : 2015-01-15 VeriSign Sarl
+नेट
+
+// xn--cck2b3b : 2015-02-26 Amazon EU S.à r.l.
+ストア
+
+// xn--cg4bki : 2013-09-27 SAMSUNG SDS CO., LTD
+삼성
+
+// xn--czr694b : 2014-01-16 HU YI GLOBAL INFORMATION RESOURCES (HOLDING) COMPANY.HONGKONG LIMITED
+商标
+
+// xn--czrs0t : 2013-12-19 Wild Island, LLC
+商店
+
+// xn--czru2d : 2013-11-21 Zodiac Capricorn Limited
+商城
+
+// xn--d1acj3b : 2013-11-20 The Foundation for Network Initiatives “The Smart Internet”
+дети
+
+// xn--eckvdtc9d : 2014-12-18 Amazon EU S.à r.l.
+ポイント
+
+// xn--efvy88h : 2014-08-22 Xinhua News Agency Guangdong Branch 新华通讯社广东分社
+新闻
+
+// xn--estv75g : 2015-02-19 Industrial and Commercial Bank of China Limited
+工行
+
+// xn--fct429k : 2015-04-09 Amazon EU S.à r.l.
+家電
+
+// xn--fhbei : 2015-01-15 VeriSign Sarl
+كوم
+
+// xn--fiq228c5hs : 2013-09-08 TLD REGISTRY LIMITED
+中文网
+
+// xn--fiq64b : 2013-10-14 CITIC Group Corporation
+中信
+
+// xn--fjq720a : 2014-05-22 Will Bloom, LLC
+娱乐
+
+// xn--flw351e : 2014-07-31 Charleston Road Registry Inc.
+谷歌
+
+// xn--fzys8d69uvgm : 2015-05-14 PCCW Enterprises Limited
+電訊盈科
+
+// xn--g2xx48c : 2015-01-30 Minds + Machines Group Limited
+购物
+
+// xn--gckr3f0f : 2015-02-26 Amazon EU S.à r.l.
+クラウド
+
+// xn--hxt814e : 2014-05-15 Zodiac Libra Limited
+网店
+
+// xn--i1b6b1a6a2e : 2013-11-14 Public Interest Registry
+संगठन
+
+// xn--imr513n : 2014-12-11 HU YI GLOBAL INFORMATION RESOURCES (HOLDING) COMPANY. HONGKONG LIMITED
+餐厅
+
+// xn--io0a7i : 2013-11-14 Computer Network Information Center of Chinese Academy of Sciences (China Internet Network Information Center)
+网络
+
+// xn--j1aef : 2015-01-15 VeriSign Sarl
+ком
+
+// xn--jlq61u9w7b : 2015-01-08 Nokia Corporation
+诺基亚
+
+// xn--jvr189m : 2015-02-26 Amazon EU S.à r.l.
+食品
+
+// xn--kcrx77d1x4a : 2014-11-07 Koninklijke Philips N.V.
+飞利浦
+
+// xn--kpu716f : 2014-12-22 Richemont DNS Inc.
+手表
+
+// xn--kput3i : 2014-02-13 Beijing RITT-Net Technology Development Co., Ltd
+手机
+
+// xn--mgba3a3ejt : 2014-11-20 Aramco Services Company
+ارامكو
+
+// xn--mgba7c0bbn0a : 2015-05-14 Crescent Holding GmbH
+العليان
+
+// xn--mgbab2bd : 2013-10-31 CORE Association
+بازار
+
+// xn--mgbb9fbpob : 2014-12-18 GreenTech Consultancy Company W.L.L.
+موبايلي
+
+// xn--mgbt3dhd : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
+همراه
+
+// xn--mk1bu44c : 2015-01-15 VeriSign Sarl
+닷컴
+
+// xn--mxtq1m : 2014-03-06 Net-Chinese Co., Ltd.
+政府
+
+// xn--ngbc5azd : 2013-07-13 International Domain Registry Pty. Ltd.
+شبكة
+
+// xn--ngbe9e0a : 2014-12-04 Kuwait Finance House
+بيتك
+
+// xn--nqv7f : 2013-11-14 Public Interest Registry
+机构
+
+// xn--nqv7fs00ema : 2013-11-14 Public Interest Registry
+组织机构
+
+// xn--nyqy26a : 2014-11-07 Stable Tone Limited
+健康
+
+// xn--p1acf : 2013-12-12 Rusnames Limited
+рус
+
+// xn--pbt977c : 2014-12-22 Richemont DNS Inc.
+珠宝
+
+// xn--pssy2u : 2015-01-15 VeriSign Sarl
+大拿
+
+// xn--q9jyb4c : 2013-09-17 Charleston Road Registry Inc.
+みんな
+
+// xn--qcka1pmc : 2014-07-31 Charleston Road Registry Inc.
+グーグル
+
+// xn--rhqv96g : 2013-09-11 Stable Tone Limited
+世界
+
+// xn--rovu88b : 2015-02-26 Amazon EU S.à r.l.
+書籍
+
+// xn--ses554g : 2014-01-16
+网址
+
+// xn--t60b56a : 2015-01-15 VeriSign Sarl
+닷넷
+
+// xn--tckwe : 2015-01-15 VeriSign Sarl
+コム
+
+// xn--unup4y : 2013-07-14 Spring Fields, LLC
+游戏
+
+// xn--vermgensberater-ctb : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG
+vermögensberater
+
+// xn--vermgensberatung-pwb : 2014-06-23 Deutsche Vermögensberatung Aktiengesellschaft DVAG
+vermögensberatung
+
+// xn--vhquv : 2013-08-27 Dash McCook, LLC
+企业
+
+// xn--vuq861b : 2014-10-16 Beijing Tele-info Network Technology Co., Ltd.
+信息
+
+// xn--w4r85el8fhu5dnra : 2015-04-30 Kerry Trading Co. Limited
+嘉里大酒店
+
+// xn--xhq521b : 2013-11-14 Guangzhou YU Wei Information Technology Co., Ltd.
+广东
+
+// xn--zfr164b : 2013-11-08 China Organizational Name Administration Center
+政务
+
+// xperia : 2015-05-14 Sony Mobile Communications AB
+xperia
+
+// xyz : 2013-12-05 XYZ.COM LLC
+xyz
+
+// yachts : 2014-01-09 DERYachts, LLC
+yachts
+
+// yahoo : 2015-04-02 Yahoo! Domain Services Inc.
+yahoo
+
+// yamaxun : 2014-12-18 Amazon EU S.à r.l.
+yamaxun
+
+// yandex : 2014-04-10 YANDEX, LLC
+yandex
+
+// yodobashi : 2014-11-20 YODOBASHI CAMERA CO.,LTD.
+yodobashi
+
+// yoga : 2014-05-29 Top Level Domain Holdings Limited
+yoga
+
+// yokohama : 2013-12-12 GMO Registry, Inc.
+yokohama
+
+// you : 2015-04-09 Amazon EU S.à r.l.
+you
+
+// youtube : 2014-05-01 Charleston Road Registry Inc.
+youtube
+
+// yun : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD.
+yun
+
+// zappos : 2015-06-25 Amazon EU S.à r.l.
+zappos
+
+// zara : 2014-11-07 Industria de Diseño Textil, S.A. (INDITEX, S.A.)
+zara
+
+// zero : 2014-12-18 Amazon EU S.à r.l.
+zero
+
+// zip : 2014-05-08 Charleston Road Registry Inc.
+zip
+
+// zippo : 2015-07-02 Zadco Company
+zippo
+
+// zone : 2013-11-14 Outer Falls, LLC
+zone
+
+// zuerich : 2014-11-07 Kanton Zürich (Canton of Zurich)
+zuerich
+
+
+// ===END ICANN DOMAINS===
+// ===BEGIN PRIVATE DOMAINS===
+// (Note: these are in alphabetical order by company name)
+
+// Amazon CloudFront : https://aws.amazon.com/cloudfront/
+// Submitted by Donavan Miller <donavanm@amazon.com> 2013-03-22
+cloudfront.net
+
+// Amazon Elastic Compute Cloud: https://aws.amazon.com/ec2/
+// Submitted by Osman Surkatty <osmans@amazon.com> 2014-12-16
+ap-northeast-1.compute.amazonaws.com
+ap-southeast-1.compute.amazonaws.com
+ap-southeast-2.compute.amazonaws.com
+cn-north-1.compute.amazonaws.cn
+compute.amazonaws.cn
+compute.amazonaws.com
+compute-1.amazonaws.com
+eu-west-1.compute.amazonaws.com
+eu-central-1.compute.amazonaws.com
+sa-east-1.compute.amazonaws.com
+us-east-1.amazonaws.com
+us-gov-west-1.compute.amazonaws.com
+us-west-1.compute.amazonaws.com
+us-west-2.compute.amazonaws.com
+z-1.compute-1.amazonaws.com
+z-2.compute-1.amazonaws.com
+
+// Amazon Elastic Beanstalk : https://aws.amazon.com/elasticbeanstalk/
+// Submitted by Adam Stein <astein@amazon.com> 2013-04-02
+elasticbeanstalk.com
+
+// Amazon Elastic Load Balancing : https://aws.amazon.com/elasticloadbalancing/
+// Submitted by Scott Vidmar <svidmar@amazon.com> 2013-03-27
+elb.amazonaws.com
+
+// Amazon S3 : https://aws.amazon.com/s3/
+// Submitted by Eric Kinolik <kilo@amazon.com> 2015-04-08
+s3.amazonaws.com
+s3-ap-northeast-1.amazonaws.com
+s3-ap-southeast-1.amazonaws.com
+s3-ap-southeast-2.amazonaws.com
+s3-external-1.amazonaws.com
+s3-external-2.amazonaws.com
+s3-fips-us-gov-west-1.amazonaws.com
+s3-eu-central-1.amazonaws.com
+s3-eu-west-1.amazonaws.com
+s3-sa-east-1.amazonaws.com
+s3-us-gov-west-1.amazonaws.com
+s3-us-west-1.amazonaws.com
+s3-us-west-2.amazonaws.com
+s3.cn-north-1.amazonaws.com.cn
+s3.eu-central-1.amazonaws.com
+
+// BetaInABox
+// Submitted by adrian@betainabox.com 2012-09-13
+betainabox.com
+
+// CentralNic : http://www.centralnic.com/names/domains
+// Submitted by registry <gavin.brown@centralnic.com> 2012-09-27
+ae.org
+ar.com
+br.com
+cn.com
+com.de
+com.se
+de.com
+eu.com
+gb.com
+gb.net
+hu.com
+hu.net
+jp.net
+jpn.com
+kr.com
+mex.com
+no.com
+qc.com
+ru.com
+sa.com
+se.com
+se.net
+uk.com
+uk.net
+us.com
+uy.com
+za.bz
+za.com
+
+// Africa.com Web Solutions Ltd : https://registry.africa.com
+// Submitted by Gavin Brown <gavin.brown@centralnic.com> 2014-02-04
+africa.com
+
+// iDOT Services Limited : http://www.domain.gr.com
+// Submitted by Gavin Brown <gavin.brown@centralnic.com> 2014-02-04
+gr.com
+
+// Radix FZC : http://domains.in.net
+// Submitted by Gavin Brown <gavin.brown@centralnic.com> 2014-02-04
+in.net
+
+// US REGISTRY LLC : http://us.org
+// Submitted by Gavin Brown <gavin.brown@centralnic.com> 2014-02-04
+us.org
+
+// co.com Registry, LLC : https://registry.co.com
+// Submitted by Gavin Brown <gavin.brown@centralnic.com> 2014-02-04
+co.com
+
+// c.la : http://www.c.la/
+c.la
+
+// cloudControl : https://www.cloudcontrol.com/
+// Submitted by Tobias Wilken <tw@cloudcontrol.com> 2013-07-23
+cloudcontrolled.com
+cloudcontrolapp.com
+
+// co.ca : http://registry.co.ca/
+co.ca
+
+// CDN77.com : http://www.cdn77.com
+// Submitted by Jan Krpes <jan.krpes@cdn77.com> 2015-07-13
+c.cdn77.org
+cdn77-ssl.net
+r.cdn77.net
+rsc.cdn77.org
+ssl.origin.cdn77-secure.org
+
+// CoDNS B.V.
+co.nl
+co.no
+
+// Commerce Guys, SAS
+// Submitted by Damien Tournoud <damien@commerceguys.com> 2015-01-22
+*.platform.sh
+
+// Cupcake : https://cupcake.io/
+// Submitted by Jonathan Rudenberg <jonathan@cupcake.io> 2013-10-08
+cupcake.is
+
+// DreamHost : http://www.dreamhost.com/
+// Submitted by Andrew Farmer <andrew.farmer@dreamhost.com> 2012-10-02
+dreamhosters.com
+
+// DuckDNS : http://www.duckdns.org/
+// Submitted by Richard Harper <richard@duckdns.org> 2015-05-17
+duckdns.org
+
+// DynDNS.com : http://www.dyndns.com/services/dns/dyndns/
+dyndns-at-home.com
+dyndns-at-work.com
+dyndns-blog.com
+dyndns-free.com
+dyndns-home.com
+dyndns-ip.com
+dyndns-mail.com
+dyndns-office.com
+dyndns-pics.com
+dyndns-remote.com
+dyndns-server.com
+dyndns-web.com
+dyndns-wiki.com
+dyndns-work.com
+dyndns.biz
+dyndns.info
+dyndns.org
+dyndns.tv
+at-band-camp.net
+ath.cx
+barrel-of-knowledge.info
+barrell-of-knowledge.info
+better-than.tv
+blogdns.com
+blogdns.net
+blogdns.org
+blogsite.org
+boldlygoingnowhere.org
+broke-it.net
+buyshouses.net
+cechire.com
+dnsalias.com
+dnsalias.net
+dnsalias.org
+dnsdojo.com
+dnsdojo.net
+dnsdojo.org
+does-it.net
+doesntexist.com
+doesntexist.org
+dontexist.com
+dontexist.net
+dontexist.org
+doomdns.com
+doomdns.org
+dvrdns.org
+dyn-o-saur.com
+dynalias.com
+dynalias.net
+dynalias.org
+dynathome.net
+dyndns.ws
+endofinternet.net
+endofinternet.org
+endoftheinternet.org
+est-a-la-maison.com
+est-a-la-masion.com
+est-le-patron.com
+est-mon-blogueur.com
+for-better.biz
+for-more.biz
+for-our.info
+for-some.biz
+for-the.biz
+forgot.her.name
+forgot.his.name
+from-ak.com
+from-al.com
+from-ar.com
+from-az.net
+from-ca.com
+from-co.net
+from-ct.com
+from-dc.com
+from-de.com
+from-fl.com
+from-ga.com
+from-hi.com
+from-ia.com
+from-id.com
+from-il.com
+from-in.com
+from-ks.com
+from-ky.com
+from-la.net
+from-ma.com
+from-md.com
+from-me.org
+from-mi.com
+from-mn.com
+from-mo.com
+from-ms.com
+from-mt.com
+from-nc.com
+from-nd.com
+from-ne.com
+from-nh.com
+from-nj.com
+from-nm.com
+from-nv.com
+from-ny.net
+from-oh.com
+from-ok.com
+from-or.com
+from-pa.com
+from-pr.com
+from-ri.com
+from-sc.com
+from-sd.com
+from-tn.com
+from-tx.com
+from-ut.com
+from-va.com
+from-vt.com
+from-wa.com
+from-wi.com
+from-wv.com
+from-wy.com
+ftpaccess.cc
+fuettertdasnetz.de
+game-host.org
+game-server.cc
+getmyip.com
+gets-it.net
+go.dyndns.org
+gotdns.com
+gotdns.org
+groks-the.info
+groks-this.info
+ham-radio-op.net
+here-for-more.info
+hobby-site.com
+hobby-site.org
+home.dyndns.org
+homedns.org
+homeftp.net
+homeftp.org
+homeip.net
+homelinux.com
+homelinux.net
+homelinux.org
+homeunix.com
+homeunix.net
+homeunix.org
+iamallama.com
+in-the-band.net
+is-a-anarchist.com
+is-a-blogger.com
+is-a-bookkeeper.com
+is-a-bruinsfan.org
+is-a-bulls-fan.com
+is-a-candidate.org
+is-a-caterer.com
+is-a-celticsfan.org
+is-a-chef.com
+is-a-chef.net
+is-a-chef.org
+is-a-conservative.com
+is-a-cpa.com
+is-a-cubicle-slave.com
+is-a-democrat.com
+is-a-designer.com
+is-a-doctor.com
+is-a-financialadvisor.com
+is-a-geek.com
+is-a-geek.net
+is-a-geek.org
+is-a-green.com
+is-a-guru.com
+is-a-hard-worker.com
+is-a-hunter.com
+is-a-knight.org
+is-a-landscaper.com
+is-a-lawyer.com
+is-a-liberal.com
+is-a-libertarian.com
+is-a-linux-user.org
+is-a-llama.com
+is-a-musician.com
+is-a-nascarfan.com
+is-a-nurse.com
+is-a-painter.com
+is-a-patsfan.org
+is-a-personaltrainer.com
+is-a-photographer.com
+is-a-player.com
+is-a-republican.com
+is-a-rockstar.com
+is-a-socialist.com
+is-a-soxfan.org
+is-a-student.com
+is-a-teacher.com
+is-a-techie.com
+is-a-therapist.com
+is-an-accountant.com
+is-an-actor.com
+is-an-actress.com
+is-an-anarchist.com
+is-an-artist.com
+is-an-engineer.com
+is-an-entertainer.com
+is-by.us
+is-certified.com
+is-found.org
+is-gone.com
+is-into-anime.com
+is-into-cars.com
+is-into-cartoons.com
+is-into-games.com
+is-leet.com
+is-lost.org
+is-not-certified.com
+is-saved.org
+is-slick.com
+is-uberleet.com
+is-very-bad.org
+is-very-evil.org
+is-very-good.org
+is-very-nice.org
+is-very-sweet.org
+is-with-theband.com
+isa-geek.com
+isa-geek.net
+isa-geek.org
+isa-hockeynut.com
+issmarterthanyou.com
+isteingeek.de
+istmein.de
+kicks-ass.net
+kicks-ass.org
+knowsitall.info
+land-4-sale.us
+lebtimnetz.de
+leitungsen.de
+likes-pie.com
+likescandy.com
+merseine.nu
+mine.nu
+misconfused.org
+mypets.ws
+myphotos.cc
+neat-url.com
+office-on-the.net
+on-the-web.tv
+podzone.net
+podzone.org
+readmyblog.org
+saves-the-whales.com
+scrapper-site.net
+scrapping.cc
+selfip.biz
+selfip.com
+selfip.info
+selfip.net
+selfip.org
+sells-for-less.com
+sells-for-u.com
+sells-it.net
+sellsyourhome.org
+servebbs.com
+servebbs.net
+servebbs.org
+serveftp.net
+serveftp.org
+servegame.org
+shacknet.nu
+simple-url.com
+space-to-rent.com
+stuff-4-sale.org
+stuff-4-sale.us
+teaches-yoga.com
+thruhere.net
+traeumtgerade.de
+webhop.biz
+webhop.info
+webhop.net
+webhop.org
+worse-than.tv
+writesthisblog.com
+
+// EU.org https://eu.org/
+// Submitted by Pierre Beyssac <hostmaster@eu.org> 2015-04-17
+
+eu.org
+al.eu.org
+asso.eu.org
+at.eu.org
+au.eu.org
+be.eu.org
+bg.eu.org
+ca.eu.org
+cd.eu.org
+ch.eu.org
+cn.eu.org
+cy.eu.org
+cz.eu.org
+de.eu.org
+dk.eu.org
+edu.eu.org
+ee.eu.org
+es.eu.org
+fi.eu.org
+fr.eu.org
+gr.eu.org
+hr.eu.org
+hu.eu.org
+ie.eu.org
+il.eu.org
+in.eu.org
+int.eu.org
+is.eu.org
+it.eu.org
+jp.eu.org
+kr.eu.org
+lt.eu.org
+lu.eu.org
+lv.eu.org
+mc.eu.org
+me.eu.org
+mk.eu.org
+mt.eu.org
+my.eu.org
+net.eu.org
+ng.eu.org
+nl.eu.org
+no.eu.org
+nz.eu.org
+paris.eu.org
+pl.eu.org
+pt.eu.org
+q-a.eu.org
+ro.eu.org
+ru.eu.org
+se.eu.org
+si.eu.org
+sk.eu.org
+tr.eu.org
+uk.eu.org
+us.eu.org
+
+// Fastly Inc. http://www.fastly.com/
+// Submitted by Vladimir Vuksan <vladimir@fastly.com> 2013-05-31
+a.ssl.fastly.net
+b.ssl.fastly.net
+global.ssl.fastly.net
+a.prod.fastly.net
+global.prod.fastly.net
+
+// Firebase, Inc.
+// Submitted by Chris Raynor <chris@firebase.com> 2014-01-21
+firebaseapp.com
+
+// Flynn : https://flynn.io
+// Submitted by Jonathan Rudenberg <jonathan@flynn.io> 2014-07-12
+flynnhub.com
+
+// GDS : https://www.gov.uk/service-manual/operations/operating-servicegovuk-subdomains
+// Submitted by David Illsley <david.illsley@digital.cabinet-office.gov.uk> 2014-08-28
+service.gov.uk
+
+// GitHub, Inc.
+// Submitted by Ben Toews <btoews@github.com> 2014-02-06
+github.io
+githubusercontent.com
+
+// GlobeHosting, Inc.
+// Submitted by Zoltan Egresi <egresi@globehosting.com> 2013-07-12
+ro.com
+
+// Google, Inc.
+// Submitted by Eduardo Vela <evn@google.com> 2014-12-19
+appspot.com
+blogspot.ae
+blogspot.al
+blogspot.am
+blogspot.ba
+blogspot.be
+blogspot.bg
+blogspot.bj
+blogspot.ca
+blogspot.cf
+blogspot.ch
+blogspot.cl
+blogspot.co.at
+blogspot.co.id
+blogspot.co.il
+blogspot.co.ke
+blogspot.co.nz
+blogspot.co.uk
+blogspot.co.za
+blogspot.com
+blogspot.com.ar
+blogspot.com.au
+blogspot.com.br
+blogspot.com.by
+blogspot.com.co
+blogspot.com.cy
+blogspot.com.ee
+blogspot.com.eg
+blogspot.com.es
+blogspot.com.mt
+blogspot.com.ng
+blogspot.com.tr
+blogspot.com.uy
+blogspot.cv
+blogspot.cz
+blogspot.de
+blogspot.dk
+blogspot.fi
+blogspot.fr
+blogspot.gr
+blogspot.hk
+blogspot.hr
+blogspot.hu
+blogspot.ie
+blogspot.in
+blogspot.is
+blogspot.it
+blogspot.jp
+blogspot.kr
+blogspot.li
+blogspot.lt
+blogspot.lu
+blogspot.md
+blogspot.mk
+blogspot.mr
+blogspot.mx
+blogspot.my
+blogspot.nl
+blogspot.no
+blogspot.pe
+blogspot.pt
+blogspot.qa
+blogspot.re
+blogspot.ro
+blogspot.rs
+blogspot.ru
+blogspot.se
+blogspot.sg
+blogspot.si
+blogspot.sk
+blogspot.sn
+blogspot.td
+blogspot.tw
+blogspot.ug
+blogspot.vn
+codespot.com
+googleapis.com
+googlecode.com
+pagespeedmobilizer.com
+withgoogle.com
+
+// Heroku : https://www.heroku.com/
+// Submitted by Tom Maher <tmaher@heroku.com> 2013-05-02
+herokuapp.com
+herokussl.com
+
+// iki.fi
+// Submitted by Hannu Aronsson <haa@iki.fi> 2009-11-05
+iki.fi
+
+// info.at : http://www.info.at/
+biz.at
+info.at
+
+// Michau Enterprises Limited : http://www.co.pl/
+co.pl
+
+// Microsoft : http://microsoft.com
+// Submitted by Barry Dorrans <bdorrans@microsoft.com> 2014-01-24
+azurewebsites.net
+azure-mobile.net
+cloudapp.net
+
+// Mozilla Foundation : https://mozilla.org/
+// Submited by glob <glob@mozilla.com> 2015-07-06
+bmoattachments.org
+
+// Neustar Inc.
+// Submitted by Trung Tran <Trung.Tran@neustar.biz> 2015-04-23
+4u.com
+
+// NFSN, Inc. : https://www.NearlyFreeSpeech.NET/
+// Submitted by Jeff Wheelhouse <support@nearlyfreespeech.net> 2014-02-02
+nfshost.com
+
+// NYC.mn : http://www.information.nyc.mn
+// Submitted by Matthew Brown <mattbrown@nyc.mn> 2013-03-11
+nyc.mn
+
+// One Fold Media : http://www.onefoldmedia.com/
+// Submitted by Eddie Jones <eddie@onefoldmedia.com> 2014-06-10
+nid.io
+
+// Opera Software, A.S.A.
+// Submitted by Yngve Pettersen <yngve@opera.com> 2009-11-26
+operaunite.com
+
+// OutSystems
+// Submitted by Duarte Santos <domain-admin@outsystemscloud.com> 2014-03-11
+outsystemscloud.com
+
+// .pl domains (grandfathered)
+art.pl
+gliwice.pl
+krakow.pl
+poznan.pl
+wroc.pl
+zakopane.pl
+
+// priv.at : http://www.nic.priv.at/
+// Submitted by registry <lendl@nic.at> 2008-06-09
+priv.at
+
+// Red Hat, Inc. OpenShift : https://openshift.redhat.com/
+// Submitted by Tim Kramer <tkramer@rhcloud.com> 2012-10-24
+rhcloud.com
+
+// SinaAppEngine : http://sae.sina.com.cn/
+// Submitted by SinaAppEngine <saesupport@sinacloud.com> 2015-02-02
+sinaapp.com
+vipsinaapp.com
+1kapp.com
+
+// TASK geographical domains (www.task.gda.pl/uslugi/dns)
+gda.pl
+gdansk.pl
+gdynia.pl
+med.pl
+sopot.pl
+
+// UDR Limited : http://www.udr.hk.com
+// Submitted by registry <hostmaster@udr.hk.com> 2014-11-07
+hk.com
+hk.org
+ltd.hk
+inc.hk
+
+// Yola : https://www.yola.com/
+// Submitted by Stefano Rivera <stefano@yola.com> 2014-07-09
+yolasite.com
+
+// ZaNiC : http://www.za.net/
+// Submitted by registry <hostmaster@nic.za.net> 2009-10-03
+za.net
+za.org
+
+// ===END PRIVATE DOMAINS===
diff --git a/netwerk/dns/mdns/libmdns/MDNSResponderOperator.cpp b/netwerk/dns/mdns/libmdns/MDNSResponderOperator.cpp
new file mode 100644
index 000000000..72b557774
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/MDNSResponderOperator.cpp
@@ -0,0 +1,779 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "MDNSResponderOperator.h"
+#include "MDNSResponderReply.h"
+#include "mozilla/EndianUtils.h"
+#include "mozilla/Logging.h"
+#include "mozilla/ScopeExit.h"
+#include "mozilla/Unused.h"
+#include "nsComponentManagerUtils.h"
+#include "nsCOMPtr.h"
+#include "nsDebug.h"
+#include "nsDNSServiceInfo.h"
+#include "nsHashPropertyBag.h"
+#include "nsIProperty.h"
+#include "nsISimpleEnumerator.h"
+#include "nsIVariant.h"
+#include "nsServiceManagerUtils.h"
+#include "nsNetAddr.h"
+#include "nsNetCID.h"
+#include "nsSocketTransportService2.h"
+#include "nsThreadUtils.h"
+#include "nsXPCOMCID.h"
+#include "private/pprio.h"
+
+#include "nsASocketHandler.h"
+
+namespace mozilla {
+namespace net {
+
+static LazyLogModule gMDNSLog("MDNSResponderOperator");
+#undef LOG_I
+#define LOG_I(...) MOZ_LOG(mozilla::net::gMDNSLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
+#undef LOG_E
+#define LOG_E(...) MOZ_LOG(mozilla::net::gMDNSLog, mozilla::LogLevel::Error, (__VA_ARGS__))
+
+class MDNSResponderOperator::ServiceWatcher final
+ : public nsASocketHandler
+{
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+
+ // nsASocketHandler methods
+ virtual void OnSocketReady(PRFileDesc* fd, int16_t outFlags) override
+ {
+ MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
+ MOZ_ASSERT(fd == mFD);
+
+ if (outFlags & (PR_POLL_ERR | PR_POLL_HUP | PR_POLL_NVAL)) {
+ LOG_E("error polling on listening socket (%p)", fd);
+ mCondition = NS_ERROR_UNEXPECTED;
+ }
+
+ if (!(outFlags & PR_POLL_READ)) {
+ return;
+ }
+
+ DNSServiceProcessResult(mService);
+ }
+
+ virtual void OnSocketDetached(PRFileDesc *fd) override
+ {
+ MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
+ MOZ_ASSERT(mThread);
+ MOZ_ASSERT(fd == mFD);
+
+ if (!mFD) {
+ return;
+ }
+
+ // Bug 1175387: do not double close the handle here.
+ PR_ChangeFileDescNativeHandle(mFD, -1);
+ PR_Close(mFD);
+ mFD = nullptr;
+
+ mThread->Dispatch(NewRunnableMethod(this, &ServiceWatcher::Deallocate),
+ NS_DISPATCH_NORMAL);
+ }
+
+ virtual void IsLocal(bool *aIsLocal) override { *aIsLocal = true; }
+
+ virtual void KeepWhenOffline(bool *aKeepWhenOffline) override
+ {
+ *aKeepWhenOffline = true;
+ }
+
+ virtual uint64_t ByteCountSent() override { return 0; }
+ virtual uint64_t ByteCountReceived() override { return 0; }
+
+ explicit ServiceWatcher(DNSServiceRef aService,
+ MDNSResponderOperator* aOperator)
+ : mThread(nullptr)
+ , mSts(nullptr)
+ , mOperatorHolder(aOperator)
+ , mService(aService)
+ , mFD(nullptr)
+ , mAttached(false)
+ {
+ if (!gSocketTransportService)
+ {
+ nsCOMPtr<nsISocketTransportService> sts =
+ do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID);
+ }
+ }
+
+ nsresult Init()
+ {
+ MOZ_ASSERT(PR_GetCurrentThread() != gSocketThread);
+ mThread = NS_GetCurrentThread();
+
+ if (!mService) {
+ return NS_OK;
+ }
+
+ if (!gSocketTransportService) {
+ return NS_ERROR_FAILURE;
+ }
+ mSts = gSocketTransportService;
+
+ int osfd = DNSServiceRefSockFD(mService);
+ if (osfd == -1) {
+ return NS_ERROR_FAILURE;
+ }
+
+ mFD = PR_ImportFile(osfd);
+ return PostEvent(&ServiceWatcher::OnMsgAttach);
+ }
+
+ void Close()
+ {
+ MOZ_ASSERT(PR_GetCurrentThread() != gSocketThread);
+
+ if (!gSocketTransportService) {
+ Deallocate();
+ return;
+ }
+
+ PostEvent(&ServiceWatcher::OnMsgClose);
+ }
+
+private:
+ ~ServiceWatcher() = default;
+
+ void Deallocate()
+ {
+ if (mService) {
+ DNSServiceRefDeallocate(mService);
+ mService = nullptr;
+ }
+ mOperatorHolder = nullptr;
+ }
+
+ nsresult PostEvent(void(ServiceWatcher::*func)(void))
+ {
+ return gSocketTransportService->Dispatch(NewRunnableMethod(this, func),
+ NS_DISPATCH_NORMAL);
+ }
+
+ void OnMsgClose()
+ {
+ MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
+
+ if (NS_FAILED(mCondition)) {
+ return;
+ }
+
+ // tear down socket. this signals the STS to detach our socket handler.
+ mCondition = NS_BINDING_ABORTED;
+
+ // if we are attached, then socket transport service will call our
+ // OnSocketDetached method automatically. Otherwise, we have to call it
+ // (and thus close the socket) manually.
+ if (!mAttached) {
+ OnSocketDetached(mFD);
+ }
+ }
+
+ void OnMsgAttach()
+ {
+ MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
+
+ if (NS_FAILED(mCondition)) {
+ return;
+ }
+
+ mCondition = TryAttach();
+
+ // if we hit an error while trying to attach then bail...
+ if (NS_FAILED(mCondition)) {
+ NS_ASSERTION(!mAttached, "should not be attached already");
+ OnSocketDetached(mFD);
+ }
+
+ }
+
+ nsresult TryAttach()
+ {
+ MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
+
+ nsresult rv;
+
+ if (!gSocketTransportService) {
+ return NS_ERROR_FAILURE;
+ }
+
+ //
+ // find out if it is going to be ok to attach another socket to the STS.
+ // if not then we have to wait for the STS to tell us that it is ok.
+ // the notification is asynchronous, which means that when we could be
+ // in a race to call AttachSocket once notified. for this reason, when
+ // we get notified, we just re-enter this function. as a result, we are
+ // sure to ask again before calling AttachSocket. in this way we deal
+ // with the race condition. though it isn't the most elegant solution,
+ // it is far simpler than trying to build a system that would guarantee
+ // FIFO ordering (which wouldn't even be that valuable IMO). see bug
+ // 194402 for more info.
+ //
+ if (!gSocketTransportService->CanAttachSocket()) {
+ nsCOMPtr<nsIRunnable> event =
+ NewRunnableMethod(this, &ServiceWatcher::OnMsgAttach);
+
+ nsresult rv = gSocketTransportService->NotifyWhenCanAttachSocket(event);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ }
+
+ //
+ // ok, we can now attach our socket to the STS for polling
+ //
+ rv = gSocketTransportService->AttachSocket(mFD, this);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ mAttached = true;
+
+ //
+ // now, configure our poll flags for listening...
+ //
+ mPollFlags = (PR_POLL_READ | PR_POLL_EXCEPT);
+
+ return NS_OK;
+ }
+
+ nsCOMPtr<nsIThread> mThread;
+ RefPtr<nsSocketTransportService> mSts;
+ RefPtr<MDNSResponderOperator> mOperatorHolder;
+ DNSServiceRef mService;
+ PRFileDesc* mFD;
+ bool mAttached;
+};
+
+NS_IMPL_ISUPPORTS(MDNSResponderOperator::ServiceWatcher, nsISupports)
+
+MDNSResponderOperator::MDNSResponderOperator()
+ : mService(nullptr)
+ , mWatcher(nullptr)
+ , mThread(NS_GetCurrentThread())
+ , mIsCancelled(false)
+{
+}
+
+MDNSResponderOperator::~MDNSResponderOperator()
+{
+ Stop();
+}
+
+nsresult
+MDNSResponderOperator::Start()
+{
+ if (mIsCancelled) {
+ return NS_OK;
+ }
+
+ if (IsServing()) {
+ Stop();
+ }
+
+ return NS_OK;
+}
+
+nsresult
+MDNSResponderOperator::Stop()
+{
+ return ResetService(nullptr);
+}
+
+nsresult
+MDNSResponderOperator::ResetService(DNSServiceRef aService)
+{
+ nsresult rv;
+
+ if (aService != mService) {
+ if (mWatcher) {
+ mWatcher->Close();
+ mWatcher = nullptr;
+ }
+
+ if (aService) {
+ RefPtr<ServiceWatcher> watcher = new ServiceWatcher(aService, this);
+ if (NS_WARN_IF(NS_FAILED(rv = watcher->Init()))) {
+ return rv;
+ }
+ mWatcher = watcher;
+ }
+
+ mService = aService;
+ }
+ return NS_OK;
+}
+
+BrowseOperator::BrowseOperator(const nsACString& aServiceType,
+ nsIDNSServiceDiscoveryListener* aListener)
+ : MDNSResponderOperator()
+ , mServiceType(aServiceType)
+ , mListener(aListener)
+{
+}
+
+nsresult
+BrowseOperator::Start()
+{
+ nsresult rv;
+ if (NS_WARN_IF(NS_FAILED(rv = MDNSResponderOperator::Start()))) {
+ return rv;
+ }
+
+ DNSServiceRef service = nullptr;
+ DNSServiceErrorType err = DNSServiceBrowse(&service,
+ 0,
+ kDNSServiceInterfaceIndexAny,
+ mServiceType.get(),
+ nullptr,
+ &BrowseReplyRunnable::Reply,
+ this);
+ NS_WARNING_ASSERTION(kDNSServiceErr_NoError == err, "DNSServiceBrowse fail");
+
+ if (mListener) {
+ if (kDNSServiceErr_NoError == err) {
+ mListener->OnDiscoveryStarted(mServiceType);
+ } else {
+ mListener->OnStartDiscoveryFailed(mServiceType, err);
+ }
+ }
+
+ if (NS_WARN_IF(kDNSServiceErr_NoError != err)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return ResetService(service);
+}
+
+nsresult
+BrowseOperator::Stop()
+{
+ bool isServing = IsServing();
+ nsresult rv = MDNSResponderOperator::Stop();
+
+ if (isServing && mListener) {
+ if (NS_SUCCEEDED(rv)) {
+ mListener->OnDiscoveryStopped(mServiceType);
+ } else {
+ mListener->OnStopDiscoveryFailed(mServiceType,
+ static_cast<uint32_t>(rv));
+ }
+ }
+
+ return rv;
+}
+
+void
+BrowseOperator::Reply(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ uint32_t aInterfaceIndex,
+ DNSServiceErrorType aErrorCode,
+ const nsACString& aServiceName,
+ const nsACString& aRegType,
+ const nsACString& aReplyDomain)
+{
+ MOZ_ASSERT(GetThread() == NS_GetCurrentThread());
+
+ if (NS_WARN_IF(kDNSServiceErr_NoError != aErrorCode)) {
+ LOG_E("BrowseOperator::Reply (%d)", aErrorCode);
+ if (mListener) {
+ mListener->OnStartDiscoveryFailed(mServiceType, aErrorCode);
+ }
+ return;
+ }
+
+ if (!mListener) { return; }
+ nsCOMPtr<nsIDNSServiceInfo> info = new nsDNSServiceInfo();
+
+ if (NS_WARN_IF(!info)) { return; }
+ if (NS_WARN_IF(NS_FAILED(info->SetServiceName(aServiceName)))) { return; }
+ if (NS_WARN_IF(NS_FAILED(info->SetServiceType(aRegType)))) { return; }
+ if (NS_WARN_IF(NS_FAILED(info->SetDomainName(aReplyDomain)))) { return; }
+
+ if (aFlags & kDNSServiceFlagsAdd) {
+ mListener->OnServiceFound(info);
+ } else {
+ mListener->OnServiceLost(info);
+ }
+}
+
+RegisterOperator::RegisterOperator(nsIDNSServiceInfo* aServiceInfo,
+ nsIDNSRegistrationListener* aListener)
+ : MDNSResponderOperator()
+ , mServiceInfo(aServiceInfo)
+ , mListener(aListener)
+{
+}
+
+nsresult
+RegisterOperator::Start()
+{
+ nsresult rv;
+
+ rv = MDNSResponderOperator::Start();
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return rv;
+ }
+ uint16_t port;
+ if (NS_WARN_IF(NS_FAILED(rv = mServiceInfo->GetPort(&port)))) {
+ return rv;
+ }
+ nsAutoCString type;
+ if (NS_WARN_IF(NS_FAILED(rv = mServiceInfo->GetServiceType(type)))) {
+ return rv;
+ }
+
+ TXTRecordRef txtRecord;
+ char buf[TXT_BUFFER_SIZE] = { 0 };
+ TXTRecordCreate(&txtRecord, TXT_BUFFER_SIZE, buf);
+
+ nsCOMPtr<nsIPropertyBag2> attributes;
+ if (NS_FAILED(rv = mServiceInfo->GetAttributes(getter_AddRefs(attributes)))) {
+ LOG_I("register: no attributes");
+ } else {
+ nsCOMPtr<nsISimpleEnumerator> enumerator;
+ if (NS_WARN_IF(NS_FAILED(rv =
+ attributes->GetEnumerator(getter_AddRefs(enumerator))))) {
+ return rv;
+ }
+
+ bool hasMoreElements;
+ while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreElements)) &&
+ hasMoreElements) {
+ nsCOMPtr<nsISupports> element;
+ MOZ_ALWAYS_SUCCEEDS(enumerator->GetNext(getter_AddRefs(element)));
+ nsCOMPtr<nsIProperty> property = do_QueryInterface(element);
+ MOZ_ASSERT(property);
+
+ nsAutoString name;
+ nsCOMPtr<nsIVariant> value;
+ MOZ_ALWAYS_SUCCEEDS(property->GetName(name));
+ MOZ_ALWAYS_SUCCEEDS(property->GetValue(getter_AddRefs(value)));
+
+ nsAutoCString str;
+ if (NS_WARN_IF(NS_FAILED(value->GetAsACString(str)))) {
+ continue;
+ }
+
+ TXTRecordSetValue(&txtRecord,
+ /* it's safe because key name is ASCII only. */
+ NS_LossyConvertUTF16toASCII(name).get(),
+ str.Length(),
+ str.get());
+ }
+ }
+
+ nsAutoCString host;
+ nsAutoCString name;
+ nsAutoCString domain;
+
+ DNSServiceRef service = nullptr;
+ DNSServiceErrorType err =
+ DNSServiceRegister(&service,
+ 0,
+ 0,
+ NS_SUCCEEDED(mServiceInfo->GetServiceName(name)) ?
+ name.get() : nullptr,
+ type.get(),
+ NS_SUCCEEDED(mServiceInfo->GetDomainName(domain)) ?
+ domain.get() : nullptr,
+ NS_SUCCEEDED(mServiceInfo->GetHost(host)) ?
+ host.get() : nullptr,
+ NativeEndian::swapToNetworkOrder(port),
+ TXTRecordGetLength(&txtRecord),
+ TXTRecordGetBytesPtr(&txtRecord),
+ &RegisterReplyRunnable::Reply,
+ this);
+ NS_WARNING_ASSERTION(kDNSServiceErr_NoError == err,
+ "DNSServiceRegister fail");
+
+ TXTRecordDeallocate(&txtRecord);
+
+ if (NS_WARN_IF(kDNSServiceErr_NoError != err)) {
+ if (mListener) {
+ mListener->OnRegistrationFailed(mServiceInfo, err);
+ }
+ return NS_ERROR_FAILURE;
+ }
+
+ return ResetService(service);
+}
+
+nsresult
+RegisterOperator::Stop()
+{
+ bool isServing = IsServing();
+ nsresult rv = MDNSResponderOperator::Stop();
+
+ if (isServing && mListener) {
+ if (NS_SUCCEEDED(rv)) {
+ mListener->OnServiceUnregistered(mServiceInfo);
+ } else {
+ mListener->OnUnregistrationFailed(mServiceInfo,
+ static_cast<uint32_t>(rv));
+ }
+ }
+
+ return rv;
+}
+
+void
+RegisterOperator::Reply(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ DNSServiceErrorType aErrorCode,
+ const nsACString& aName,
+ const nsACString& aRegType,
+ const nsACString& aDomain)
+{
+ MOZ_ASSERT(GetThread() == NS_GetCurrentThread());
+
+ if (kDNSServiceErr_NoError != aErrorCode) {
+ LOG_E("RegisterOperator::Reply (%d)", aErrorCode);
+ }
+
+ if (!mListener) { return; }
+ nsCOMPtr<nsIDNSServiceInfo> info = new nsDNSServiceInfo(mServiceInfo);
+ if (NS_WARN_IF(NS_FAILED(info->SetServiceName(aName)))) { return; }
+ if (NS_WARN_IF(NS_FAILED(info->SetServiceType(aRegType)))) { return; }
+ if (NS_WARN_IF(NS_FAILED(info->SetDomainName(aDomain)))) { return; }
+
+ if (kDNSServiceErr_NoError == aErrorCode) {
+ if (aFlags & kDNSServiceFlagsAdd) {
+ mListener->OnServiceRegistered(info);
+ } else {
+ // If a successfully-registered name later suffers a name conflict
+ // or similar problem and has to be deregistered, the callback will
+ // be invoked with the kDNSServiceFlagsAdd flag not set.
+ LOG_E("RegisterOperator::Reply: deregister");
+ if (NS_WARN_IF(NS_FAILED(Stop()))) {
+ return;
+ }
+ }
+ } else {
+ mListener->OnRegistrationFailed(info, aErrorCode);
+ }
+}
+
+ResolveOperator::ResolveOperator(nsIDNSServiceInfo* aServiceInfo,
+ nsIDNSServiceResolveListener* aListener)
+ : MDNSResponderOperator()
+ , mServiceInfo(aServiceInfo)
+ , mListener(aListener)
+{
+}
+
+nsresult
+ResolveOperator::Start()
+{
+ nsresult rv;
+ if (NS_WARN_IF(NS_FAILED(rv = MDNSResponderOperator::Start()))) {
+ return rv;
+ }
+
+ nsAutoCString name;
+ mServiceInfo->GetServiceName(name);
+ nsAutoCString type;
+ mServiceInfo->GetServiceType(type);
+ nsAutoCString domain;
+ mServiceInfo->GetDomainName(domain);
+
+ LOG_I("Resolve: (%s), (%s), (%s)", name.get(), type.get(), domain.get());
+
+ DNSServiceRef service = nullptr;
+ DNSServiceErrorType err =
+ DNSServiceResolve(&service,
+ 0,
+ kDNSServiceInterfaceIndexAny,
+ name.get(),
+ type.get(),
+ domain.get(),
+ (DNSServiceResolveReply)&ResolveReplyRunnable::Reply,
+ this);
+
+ if (NS_WARN_IF(kDNSServiceErr_NoError != err)) {
+ if (mListener) {
+ mListener->OnResolveFailed(mServiceInfo, err);
+ }
+ return NS_ERROR_FAILURE;
+ }
+
+ return ResetService(service);
+}
+
+void
+ResolveOperator::Reply(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ uint32_t aInterfaceIndex,
+ DNSServiceErrorType aErrorCode,
+ const nsACString& aFullName,
+ const nsACString& aHostTarget,
+ uint16_t aPort,
+ uint16_t aTxtLen,
+ const unsigned char* aTxtRecord)
+{
+ MOZ_ASSERT(GetThread() == NS_GetCurrentThread());
+
+ auto guard = MakeScopeExit([&] {
+ Unused << NS_WARN_IF(NS_FAILED(Stop()));
+ });
+
+ if (NS_WARN_IF(kDNSServiceErr_NoError != aErrorCode)) {
+ LOG_E("ResolveOperator::Reply (%d)", aErrorCode);
+ return;
+ }
+
+ // Resolve TXT record
+ int count = TXTRecordGetCount(aTxtLen, aTxtRecord);
+ LOG_I("resolve: txt count = %d, len = %d", count, aTxtLen);
+ nsCOMPtr<nsIWritablePropertyBag2> attributes = new nsHashPropertyBag();
+ if (NS_WARN_IF(!attributes)) {
+ return;
+ }
+ if (count) {
+ for (int i = 0; i < count; ++i) {
+ char key[TXT_BUFFER_SIZE] = { '\0' };
+ uint8_t vSize = 0;
+ const void* value = nullptr;
+ if (kDNSServiceErr_NoError !=
+ TXTRecordGetItemAtIndex(aTxtLen,
+ aTxtRecord,
+ i,
+ TXT_BUFFER_SIZE,
+ key,
+ &vSize,
+ &value)) {
+ break;
+ }
+
+ nsAutoCString str(reinterpret_cast<const char*>(value), vSize);
+ LOG_I("resolve TXT: (%d) %s=%s", vSize, key, str.get());
+
+ if (NS_WARN_IF(NS_FAILED(attributes->SetPropertyAsACString(
+ /* it's safe to convert because key name is ASCII only. */
+ NS_ConvertASCIItoUTF16(key),
+ str)))) {
+ break;
+ }
+ }
+ }
+
+ if (!mListener) { return; }
+ nsCOMPtr<nsIDNSServiceInfo> info = new nsDNSServiceInfo(mServiceInfo);
+ if (NS_WARN_IF(NS_FAILED(info->SetHost(aHostTarget)))) { return; }
+ if (NS_WARN_IF(NS_FAILED(info->SetPort(aPort)))) { return; }
+ if (NS_WARN_IF(NS_FAILED(info->SetAttributes(attributes)))) { return; }
+
+ if (kDNSServiceErr_NoError == aErrorCode) {
+ GetAddrInfor(info);
+ }
+ else {
+ mListener->OnResolveFailed(info, aErrorCode);
+ Unused << NS_WARN_IF(NS_FAILED(Stop()));
+ }
+}
+
+void
+ResolveOperator::GetAddrInfor(nsIDNSServiceInfo* aServiceInfo)
+{
+ RefPtr<GetAddrInfoOperator> getAddreOp = new GetAddrInfoOperator(aServiceInfo,
+ mListener);
+ Unused << NS_WARN_IF(NS_FAILED(getAddreOp->Start()));
+}
+
+GetAddrInfoOperator::GetAddrInfoOperator(nsIDNSServiceInfo* aServiceInfo,
+ nsIDNSServiceResolveListener* aListener)
+ : MDNSResponderOperator()
+ , mServiceInfo(aServiceInfo)
+ , mListener(aListener)
+{
+}
+
+nsresult
+GetAddrInfoOperator::Start()
+{
+ nsresult rv;
+ if (NS_WARN_IF(NS_FAILED(rv = MDNSResponderOperator::Start()))) {
+ return rv;
+ }
+
+ nsAutoCString host;
+ mServiceInfo->GetHost(host);
+
+ LOG_I("GetAddrInfo: (%s)", host.get());
+
+ DNSServiceRef service = nullptr;
+ DNSServiceErrorType err =
+ DNSServiceGetAddrInfo(&service,
+ kDNSServiceFlagsForceMulticast,
+ kDNSServiceInterfaceIndexAny,
+ kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6,
+ host.get(),
+ (DNSServiceGetAddrInfoReply)&GetAddrInfoReplyRunnable::Reply,
+ this);
+
+ if (NS_WARN_IF(kDNSServiceErr_NoError != err)) {
+ if (mListener) {
+ mListener->OnResolveFailed(mServiceInfo, err);
+ }
+ return NS_ERROR_FAILURE;
+ }
+
+ return ResetService(service);
+}
+
+void
+GetAddrInfoOperator::Reply(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ uint32_t aInterfaceIndex,
+ DNSServiceErrorType aErrorCode,
+ const nsACString& aHostName,
+ const NetAddr& aAddress,
+ uint32_t aTTL)
+{
+ MOZ_ASSERT(GetThread() == NS_GetCurrentThread());
+
+ auto guard = MakeScopeExit([&] {
+ Unused << NS_WARN_IF(NS_FAILED(Stop()));
+ });
+
+ if (NS_WARN_IF(kDNSServiceErr_NoError != aErrorCode)) {
+ LOG_E("GetAddrInfoOperator::Reply (%d)", aErrorCode);
+ return;
+ }
+
+ if (!mListener) { return; }
+
+ NetAddr addr = aAddress;
+ nsCOMPtr<nsINetAddr> address = new nsNetAddr(&addr);
+ nsCString addressStr;
+ if (NS_WARN_IF(NS_FAILED(address->GetAddress(addressStr)))) { return; }
+
+ nsCOMPtr<nsIDNSServiceInfo> info = new nsDNSServiceInfo(mServiceInfo);
+ if (NS_WARN_IF(NS_FAILED(info->SetAddress(addressStr)))) { return; }
+
+ /**
+ * |kDNSServiceFlagsMoreComing| means this callback will be one or more
+ * callback events later, so this instance should be kept alive until all
+ * follow-up events are processed.
+ */
+ if (aFlags & kDNSServiceFlagsMoreComing) {
+ guard.release();
+ }
+
+ if (kDNSServiceErr_NoError == aErrorCode) {
+ mListener->OnServiceResolved(info);
+ } else {
+ mListener->OnResolveFailed(info, aErrorCode);
+ }
+}
+
+} // namespace net
+} // namespace mozilla
diff --git a/netwerk/dns/mdns/libmdns/MDNSResponderOperator.h b/netwerk/dns/mdns/libmdns/MDNSResponderOperator.h
new file mode 100644
index 000000000..a932baa7c
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/MDNSResponderOperator.h
@@ -0,0 +1,152 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_netwerk_dns_mdns_libmdns_MDNSResponderOperator_h
+#define mozilla_netwerk_dns_mdns_libmdns_MDNSResponderOperator_h
+
+#include "dns_sd.h"
+#include "mozilla/Atomics.h"
+#include "mozilla/RefPtr.h"
+#include "nsCOMPtr.h"
+#include "nsIDNSServiceDiscovery.h"
+#include "nsIThread.h"
+#include "nsString.h"
+
+namespace mozilla {
+namespace net {
+
+class MDNSResponderOperator
+{
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MDNSResponderOperator)
+
+public:
+ MDNSResponderOperator();
+
+ virtual nsresult Start();
+ virtual nsresult Stop();
+ void Cancel() { mIsCancelled = true; }
+ nsIThread* GetThread() const { return mThread; }
+
+protected:
+ virtual ~MDNSResponderOperator();
+
+ bool IsServing() const { return mService; }
+ nsresult ResetService(DNSServiceRef aService);
+
+private:
+ class ServiceWatcher;
+
+ DNSServiceRef mService;
+ RefPtr<ServiceWatcher> mWatcher;
+ nsCOMPtr<nsIThread> mThread; // remember caller thread for callback
+ Atomic<bool> mIsCancelled;
+};
+
+class BrowseOperator final : public MDNSResponderOperator
+{
+public:
+ BrowseOperator(const nsACString& aServiceType,
+ nsIDNSServiceDiscoveryListener* aListener);
+
+ nsresult Start() override;
+ nsresult Stop() override;
+
+ void Reply(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ uint32_t aInterfaceIndex,
+ DNSServiceErrorType aErrorCode,
+ const nsACString& aServiceName,
+ const nsACString& aRegType,
+ const nsACString& aReplyDomain);
+
+private:
+ ~BrowseOperator() = default;
+
+ nsCString mServiceType;
+ nsCOMPtr<nsIDNSServiceDiscoveryListener> mListener;
+};
+
+class RegisterOperator final : public MDNSResponderOperator
+{
+ enum { TXT_BUFFER_SIZE = 256 };
+
+public:
+ RegisterOperator(nsIDNSServiceInfo* aServiceInfo,
+ nsIDNSRegistrationListener* aListener);
+
+ nsresult Start() override;
+ nsresult Stop() override;
+
+ void Reply(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ DNSServiceErrorType aErrorCode,
+ const nsACString& aName,
+ const nsACString& aRegType,
+ const nsACString& aDomain);
+
+private:
+ ~RegisterOperator() = default;
+
+ nsCOMPtr<nsIDNSServiceInfo> mServiceInfo;
+ nsCOMPtr<nsIDNSRegistrationListener> mListener;
+};
+
+class ResolveOperator final : public MDNSResponderOperator
+{
+ enum { TXT_BUFFER_SIZE = 256 };
+
+public:
+ ResolveOperator(nsIDNSServiceInfo* aServiceInfo,
+ nsIDNSServiceResolveListener* aListener);
+
+ nsresult Start() override;
+
+ void Reply(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ uint32_t aInterfaceIndex,
+ DNSServiceErrorType aErrorCode,
+ const nsACString& aFullName,
+ const nsACString& aHostTarget,
+ uint16_t aPort,
+ uint16_t aTxtLen,
+ const unsigned char* aTxtRecord);
+
+private:
+ ~ResolveOperator() = default;
+ void GetAddrInfor(nsIDNSServiceInfo* aServiceInfo);
+
+ nsCOMPtr<nsIDNSServiceInfo> mServiceInfo;
+ nsCOMPtr<nsIDNSServiceResolveListener> mListener;
+};
+
+union NetAddr;
+
+class GetAddrInfoOperator final : public MDNSResponderOperator
+{
+public:
+ GetAddrInfoOperator(nsIDNSServiceInfo* aServiceInfo,
+ nsIDNSServiceResolveListener* aListener);
+
+ nsresult Start() override;
+
+ void Reply(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ uint32_t aInterfaceIndex,
+ DNSServiceErrorType aErrorCode,
+ const nsACString& aHostName,
+ const NetAddr& aAddress,
+ uint32_t aTTL);
+
+private:
+ ~GetAddrInfoOperator() = default;
+
+ nsCOMPtr<nsIDNSServiceInfo> mServiceInfo;
+ nsCOMPtr<nsIDNSServiceResolveListener> mListener;
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif // mozilla_netwerk_dns_mdns_libmdns_MDNSResponderOperator_h
diff --git a/netwerk/dns/mdns/libmdns/MDNSResponderReply.cpp b/netwerk/dns/mdns/libmdns/MDNSResponderReply.cpp
new file mode 100644
index 000000000..7aa5b3759
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/MDNSResponderReply.cpp
@@ -0,0 +1,302 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "MDNSResponderReply.h"
+#include "mozilla/EndianUtils.h"
+#include "private/pprio.h"
+
+namespace mozilla {
+namespace net {
+
+BrowseReplyRunnable::BrowseReplyRunnable(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ uint32_t aInterfaceIndex,
+ DNSServiceErrorType aErrorCode,
+ const nsACString& aServiceName,
+ const nsACString& aRegType,
+ const nsACString& aReplyDomain,
+ BrowseOperator* aContext)
+ : mSdRef(aSdRef)
+ , mFlags(aFlags)
+ , mInterfaceIndex(aInterfaceIndex)
+ , mErrorCode(aErrorCode)
+ , mServiceName(aServiceName)
+ , mRegType(aRegType)
+ , mReplyDomain(aReplyDomain)
+ , mContext(aContext)
+{
+}
+
+NS_IMETHODIMP
+BrowseReplyRunnable::Run()
+{
+ MOZ_ASSERT(mContext);
+ mContext->Reply(mSdRef,
+ mFlags,
+ mInterfaceIndex,
+ mErrorCode,
+ mServiceName,
+ mRegType,
+ mReplyDomain);
+ return NS_OK;
+}
+
+void
+BrowseReplyRunnable::Reply(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ uint32_t aInterfaceIndex,
+ DNSServiceErrorType aErrorCode,
+ const char* aServiceName,
+ const char* aRegType,
+ const char* aReplyDomain,
+ void* aContext)
+{
+ MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
+
+ BrowseOperator* obj(reinterpret_cast<BrowseOperator*>(aContext));
+ if (!obj) {
+ return;
+ }
+
+ nsCOMPtr<nsIThread> thread(obj->GetThread());
+ if (!thread) {
+ return;
+ }
+
+ thread->Dispatch(new BrowseReplyRunnable(aSdRef,
+ aFlags,
+ aInterfaceIndex,
+ aErrorCode,
+ nsCString(aServiceName),
+ nsCString(aRegType),
+ nsCString(aReplyDomain),
+ obj),
+ NS_DISPATCH_NORMAL);
+}
+
+RegisterReplyRunnable::RegisterReplyRunnable(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ DNSServiceErrorType aErrorCode,
+ const nsACString& aName,
+ const nsACString& aRegType,
+ const nsACString& domain,
+ RegisterOperator* aContext)
+ : mSdRef(aSdRef)
+ , mFlags(aFlags)
+ , mErrorCode(aErrorCode)
+ , mName(aName)
+ , mRegType(aRegType)
+ , mDomain(domain)
+ , mContext(aContext)
+{
+}
+
+NS_IMETHODIMP
+RegisterReplyRunnable::Run()
+{
+ MOZ_ASSERT(mContext);
+
+ mContext->Reply(mSdRef,
+ mFlags,
+ mErrorCode,
+ mName,
+ mRegType,
+ mDomain);
+ return NS_OK;
+}
+
+void
+RegisterReplyRunnable::Reply(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ DNSServiceErrorType aErrorCode,
+ const char* aName,
+ const char* aRegType,
+ const char* domain,
+ void* aContext)
+{
+ MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
+
+ RegisterOperator* obj(reinterpret_cast<RegisterOperator*>(aContext));
+ if (!obj) {
+ return;
+ }
+
+ nsCOMPtr<nsIThread> thread(obj->GetThread());
+ if (!thread) {
+ return;
+ }
+
+ thread->Dispatch(new RegisterReplyRunnable(aSdRef,
+ aFlags,
+ aErrorCode,
+ nsCString(aName),
+ nsCString(aRegType),
+ nsCString(domain),
+ obj),
+ NS_DISPATCH_NORMAL);
+}
+
+ResolveReplyRunnable::ResolveReplyRunnable(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ uint32_t aInterfaceIndex,
+ DNSServiceErrorType aErrorCode,
+ const nsACString& aFullName,
+ const nsACString& aHostTarget,
+ uint16_t aPort,
+ uint16_t aTxtLen,
+ const unsigned char* aTxtRecord,
+ ResolveOperator* aContext)
+ : mSdRef(aSdRef)
+ , mFlags(aFlags)
+ , mInterfaceIndex(aInterfaceIndex)
+ , mErrorCode(aErrorCode)
+ , mFullname(aFullName)
+ , mHosttarget(aHostTarget)
+ , mPort(aPort)
+ , mTxtLen(aTxtLen)
+ , mTxtRecord(new unsigned char[aTxtLen])
+ , mContext(aContext)
+{
+ if (mTxtRecord) {
+ memcpy(mTxtRecord.get(), aTxtRecord, aTxtLen);
+ }
+}
+
+ResolveReplyRunnable::~ResolveReplyRunnable()
+{
+}
+
+NS_IMETHODIMP
+ResolveReplyRunnable::Run()
+{
+ MOZ_ASSERT(mContext);
+ mContext->Reply(mSdRef,
+ mFlags,
+ mInterfaceIndex,
+ mErrorCode,
+ mFullname,
+ mHosttarget,
+ mPort,
+ mTxtLen,
+ mTxtRecord.get());
+ return NS_OK;
+}
+
+void
+ResolveReplyRunnable::Reply(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ uint32_t aInterfaceIndex,
+ DNSServiceErrorType aErrorCode,
+ const char* aFullName,
+ const char* aHostTarget,
+ uint16_t aPort,
+ uint16_t aTxtLen,
+ const unsigned char* aTxtRecord,
+ void* aContext)
+{
+ MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
+
+ ResolveOperator* obj(reinterpret_cast<ResolveOperator*>(aContext));
+ if (!obj) {
+ return;
+ }
+
+ nsCOMPtr<nsIThread> thread(obj->GetThread());
+ if (!thread) {
+ return;
+ }
+
+ thread->Dispatch(new ResolveReplyRunnable(aSdRef,
+ aFlags,
+ aInterfaceIndex,
+ aErrorCode,
+ nsCString(aFullName),
+ nsCString(aHostTarget),
+ NativeEndian::swapFromNetworkOrder(aPort),
+ aTxtLen,
+ aTxtRecord,
+ obj),
+ NS_DISPATCH_NORMAL);
+}
+
+GetAddrInfoReplyRunnable::GetAddrInfoReplyRunnable(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ uint32_t aInterfaceIndex,
+ DNSServiceErrorType aErrorCode,
+ const nsACString& aHostName,
+ const mozilla::net::NetAddr& aAddress,
+ uint32_t aTTL,
+ GetAddrInfoOperator* aContext)
+ : mSdRef(aSdRef)
+ , mFlags(aFlags)
+ , mInterfaceIndex(aInterfaceIndex)
+ , mErrorCode(aErrorCode)
+ , mHostName(aHostName)
+ , mAddress(aAddress)
+ , mTTL(aTTL)
+ , mContext(aContext)
+{
+}
+
+GetAddrInfoReplyRunnable::~GetAddrInfoReplyRunnable()
+{
+}
+
+NS_IMETHODIMP
+GetAddrInfoReplyRunnable::Run()
+{
+ MOZ_ASSERT(mContext);
+ mContext->Reply(mSdRef,
+ mFlags,
+ mInterfaceIndex,
+ mErrorCode,
+ mHostName,
+ mAddress,
+ mTTL);
+ return NS_OK;
+}
+
+void
+GetAddrInfoReplyRunnable::Reply(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ uint32_t aInterfaceIndex,
+ DNSServiceErrorType aErrorCode,
+ const char* aHostName,
+ const struct sockaddr* aAddress,
+ uint32_t aTTL,
+ void* aContext)
+{
+ MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
+
+ GetAddrInfoOperator* obj(reinterpret_cast<GetAddrInfoOperator*>(aContext));
+ if (!obj) {
+ return;
+ }
+
+ nsCOMPtr<nsIThread> thread(obj->GetThread());
+ if (!thread) {
+ return;
+ }
+
+ NetAddr address;
+ address.raw.family = aAddress->sa_family;
+
+ static_assert(sizeof(address.raw.data) >= sizeof(aAddress->sa_data),
+ "size of sockaddr.sa_data is too big");
+ memcpy(&address.raw.data, aAddress->sa_data, sizeof(aAddress->sa_data));
+
+ thread->Dispatch(new GetAddrInfoReplyRunnable(aSdRef,
+ aFlags,
+ aInterfaceIndex,
+ aErrorCode,
+ nsCString(aHostName),
+ address,
+ aTTL,
+ obj),
+ NS_DISPATCH_NORMAL);
+}
+
+} // namespace net
+} // namespace mozilla
diff --git a/netwerk/dns/mdns/libmdns/MDNSResponderReply.h b/netwerk/dns/mdns/libmdns/MDNSResponderReply.h
new file mode 100644
index 000000000..794a585f8
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/MDNSResponderReply.h
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_netwerk_dns_mdns_libmdns_MDNSResponderReply_h
+#define mozilla_netwerk_dns_mdns_libmdns_MDNSResponderReply_h
+
+#include "dns_sd.h"
+#include "MDNSResponderOperator.h"
+#include "mozilla/UniquePtr.h"
+#include "nsIThread.h"
+#include "mozilla/net/DNS.h"
+#include "mozilla/RefPtr.h"
+#include "nsThreadUtils.h"
+
+namespace mozilla {
+namespace net {
+
+class BrowseReplyRunnable final : public Runnable
+{
+public:
+ BrowseReplyRunnable(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ uint32_t aInterfaceIndex,
+ DNSServiceErrorType aErrorCode,
+ const nsACString& aServiceName,
+ const nsACString& aRegType,
+ const nsACString& aReplyDomain,
+ BrowseOperator* aContext);
+
+ NS_IMETHOD Run() override;
+
+ static void Reply(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ uint32_t aInterfaceIndex,
+ DNSServiceErrorType aErrorCode,
+ const char* aServiceName,
+ const char* aRegType,
+ const char* aReplyDomain,
+ void* aContext);
+
+private:
+ DNSServiceRef mSdRef;
+ DNSServiceFlags mFlags;
+ uint32_t mInterfaceIndex;
+ DNSServiceErrorType mErrorCode;
+ nsCString mServiceName;
+ nsCString mRegType;
+ nsCString mReplyDomain;
+ RefPtr<BrowseOperator> mContext;
+};
+
+class RegisterReplyRunnable final : public Runnable
+{
+public:
+ RegisterReplyRunnable(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ DNSServiceErrorType aErrorCode,
+ const nsACString& aName,
+ const nsACString& aRegType,
+ const nsACString& aDomain,
+ RegisterOperator* aContext);
+
+ NS_IMETHOD Run() override;
+
+ static void Reply(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ DNSServiceErrorType aErrorCode,
+ const char* aName,
+ const char* aRegType,
+ const char* aDomain,
+ void* aContext);
+
+private:
+ DNSServiceRef mSdRef;
+ DNSServiceFlags mFlags;
+ DNSServiceErrorType mErrorCode;
+ nsCString mName;
+ nsCString mRegType;
+ nsCString mDomain;
+ RefPtr<RegisterOperator> mContext;
+};
+
+class ResolveReplyRunnable final : public Runnable
+{
+public:
+ ResolveReplyRunnable(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ uint32_t aInterfaceIndex,
+ DNSServiceErrorType aErrorCode,
+ const nsACString& aFullName,
+ const nsACString& aHostTarget,
+ uint16_t aPort,
+ uint16_t aTxtLen,
+ const unsigned char* aTxtRecord,
+ ResolveOperator* aContext);
+ ~ResolveReplyRunnable();
+
+ NS_IMETHOD Run() override;
+
+ static void Reply(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ uint32_t aInterfaceIndex,
+ DNSServiceErrorType aErrorCode,
+ const char* aFullName,
+ const char* aHostTarget,
+ uint16_t aPort,
+ uint16_t aTxtLen,
+ const unsigned char* aTxtRecord,
+ void* aContext);
+
+private:
+ DNSServiceRef mSdRef;
+ DNSServiceFlags mFlags;
+ uint32_t mInterfaceIndex;
+ DNSServiceErrorType mErrorCode;
+ nsCString mFullname;
+ nsCString mHosttarget;
+ uint16_t mPort;
+ uint16_t mTxtLen;
+ UniquePtr<unsigned char> mTxtRecord;
+ RefPtr<ResolveOperator> mContext;
+};
+
+class GetAddrInfoReplyRunnable final : public Runnable
+{
+public:
+ GetAddrInfoReplyRunnable(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ uint32_t aInterfaceIndex,
+ DNSServiceErrorType aErrorCode,
+ const nsACString& aHostName,
+ const mozilla::net::NetAddr& aAddress,
+ uint32_t aTTL,
+ GetAddrInfoOperator* aContext);
+ ~GetAddrInfoReplyRunnable();
+
+ NS_IMETHOD Run() override;
+
+ static void Reply(DNSServiceRef aSdRef,
+ DNSServiceFlags aFlags,
+ uint32_t aInterfaceIndex,
+ DNSServiceErrorType aErrorCode,
+ const char* aHostName,
+ const struct sockaddr* aAddress,
+ uint32_t aTTL,
+ void* aContext);
+
+private:
+ DNSServiceRef mSdRef;
+ DNSServiceFlags mFlags;
+ uint32_t mInterfaceIndex;
+ DNSServiceErrorType mErrorCode;
+ nsCString mHostName;
+ mozilla::net::NetAddr mAddress;
+ uint32_t mTTL;
+ RefPtr<GetAddrInfoOperator> mContext;
+};
+
+} // namespace net
+} // namespace mozilla
+
+ #endif // mozilla_netwerk_dns_mdns_libmdns_MDNSResponderReply_h
diff --git a/netwerk/dns/mdns/libmdns/MulticastDNSAndroid.jsm b/netwerk/dns/mdns/libmdns/MulticastDNSAndroid.jsm
new file mode 100644
index 000000000..771f9a794
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/MulticastDNSAndroid.jsm
@@ -0,0 +1,244 @@
+// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = ["MulticastDNS"];
+
+const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/Messaging.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+var log = Cu.import("resource://gre/modules/AndroidLog.jsm", {}).AndroidLog.d.bind(null, "MulticastDNS");
+
+const FAILURE_INTERNAL_ERROR = -65537;
+
+// Helper function for sending commands to Java.
+function send(type, data, callback) {
+ let msg = {
+ type: type
+ };
+
+ for (let i in data) {
+ try {
+ msg[i] = data[i];
+ } catch (e) {
+ }
+ }
+
+ Messaging.sendRequestForResult(msg)
+ .then(result => callback(result, null),
+ err => callback(null, typeof err === "number" ? err : FAILURE_INTERNAL_ERROR));
+}
+
+// Receives service found/lost event from NsdManager
+function ServiceManager() {
+}
+
+ServiceManager.prototype = {
+ listeners: {},
+ numListeners: 0,
+
+ registerEvent: function() {
+ log("registerEvent");
+ Messaging.addListener(this.onServiceFound.bind(this), "NsdManager:ServiceFound");
+ Messaging.addListener(this.onServiceLost.bind(this), "NsdManager:ServiceLost");
+ },
+
+ unregisterEvent: function() {
+ log("unregisterEvent");
+ Messaging.removeListener("NsdManager:ServiceFound");
+ Messaging.removeListener("NsdManager:ServiceLost");
+ },
+
+ addListener: function(aServiceType, aListener) {
+ log("addListener: " + aServiceType + ", " + aListener);
+
+ if (!this.listeners[aServiceType]) {
+ this.listeners[aServiceType] = [];
+ }
+ if (this.listeners[aServiceType].includes(aListener)) {
+ log("listener already exists");
+ return;
+ }
+
+ this.listeners[aServiceType].push(aListener);
+ ++this.numListeners;
+
+ if (this.numListeners === 1) {
+ this.registerEvent();
+ }
+
+ log("listener added: " + this);
+ },
+
+ removeListener: function(aServiceType, aListener) {
+ log("removeListener: " + aServiceType + ", " + aListener);
+
+ if (!this.listeners[aServiceType]) {
+ log("listener doesn't exist");
+ return;
+ }
+ let index = this.listeners[aServiceType].indexOf(aListener);
+ if (index < 0) {
+ log("listener doesn't exist");
+ return;
+ }
+
+ this.listeners[aServiceType].splice(index, 1);
+ --this.numListeners;
+
+ if (this.numListeners === 0) {
+ this.unregisterEvent();
+ }
+
+ log("listener removed" + this);
+ },
+
+ onServiceFound: function(aServiceInfo) {
+ let listeners = this.listeners[aServiceInfo.serviceType];
+ if (listeners) {
+ for (let listener of listeners) {
+ listener.onServiceFound(aServiceInfo);
+ }
+ } else {
+ log("no listener");
+ }
+ return {};
+ },
+
+ onServiceLost: function(aServiceInfo) {
+ let listeners = this.listeners[aServiceInfo.serviceType];
+ if (listeners) {
+ for (let listener of listeners) {
+ listener.onServiceLost(aServiceInfo);
+ }
+ } else {
+ log("no listener");
+ }
+ return {};
+ }
+};
+
+// make an object from nsIPropertyBag2
+function parsePropertyBag2(bag) {
+ if (!bag || !(bag instanceof Ci.nsIPropertyBag2)) {
+ throw new TypeError("Not a property bag");
+ }
+
+ let attributes = [];
+ let enumerator = bag.enumerator;
+ while (enumerator.hasMoreElements()) {
+ let name = enumerator.getNext().QueryInterface(Ci.nsIProperty).name;
+ let value = bag.getPropertyAsACString(name);
+ attributes.push({
+ "name": name,
+ "value": value
+ });
+ }
+
+ return attributes;
+}
+
+function MulticastDNS() {
+ this.serviceManager = new ServiceManager();
+}
+
+MulticastDNS.prototype = {
+ startDiscovery: function(aServiceType, aListener) {
+ this.serviceManager.addListener(aServiceType, aListener);
+
+ let serviceInfo = {
+ serviceType: aServiceType,
+ uniqueId: aListener.uuid
+ };
+
+ send("NsdManager:DiscoverServices", serviceInfo, (result, err) => {
+ if (err) {
+ log("onStartDiscoveryFailed: " + aServiceType + " (" + err + ")");
+ this.serviceManager.removeListener(aServiceType, aListener);
+ aListener.onStartDiscoveryFailed(aServiceType, err);
+ } else {
+ aListener.onDiscoveryStarted(result);
+ }
+ });
+ },
+
+ stopDiscovery: function(aServiceType, aListener) {
+ this.serviceManager.removeListener(aServiceType, aListener);
+
+ let serviceInfo = {
+ uniqueId: aListener.uuid
+ };
+
+ send("NsdManager:StopServiceDiscovery", serviceInfo, (result, err) => {
+ if (err) {
+ log("onStopDiscoveryFailed: " + aServiceType + " (" + err + ")");
+ aListener.onStopDiscoveryFailed(aServiceType, err);
+ } else {
+ aListener.onDiscoveryStopped(aServiceType);
+ }
+ });
+ },
+
+ registerService: function(aServiceInfo, aListener) {
+ let serviceInfo = {
+ port: aServiceInfo.port,
+ serviceType: aServiceInfo.serviceType,
+ uniqueId: aListener.uuid
+ };
+
+ try {
+ serviceInfo.host = aServiceInfo.host;
+ } catch(e) {
+ // host unspecified
+ }
+ try {
+ serviceInfo.serviceName = aServiceInfo.serviceName;
+ } catch(e) {
+ // serviceName unspecified
+ }
+ try {
+ serviceInfo.attributes = parsePropertyBag2(aServiceInfo.attributes);
+ } catch(e) {
+ // attributes unspecified
+ }
+
+ send("NsdManager:RegisterService", serviceInfo, (result, err) => {
+ if (err) {
+ log("onRegistrationFailed: (" + err + ")");
+ aListener.onRegistrationFailed(aServiceInfo, err);
+ } else {
+ aListener.onServiceRegistered(result);
+ }
+ });
+ },
+
+ unregisterService: function(aServiceInfo, aListener) {
+ let serviceInfo = {
+ uniqueId: aListener.uuid
+ };
+
+ send("NsdManager:UnregisterService", serviceInfo, (result, err) => {
+ if (err) {
+ log("onUnregistrationFailed: (" + err + ")");
+ aListener.onUnregistrationFailed(aServiceInfo, err);
+ } else {
+ aListener.onServiceUnregistered(aServiceInfo);
+ }
+ });
+ },
+
+ resolveService: function(aServiceInfo, aListener) {
+ send("NsdManager:ResolveService", aServiceInfo, (result, err) => {
+ if (err) {
+ log("onResolveFailed: (" + err + ")");
+ aListener.onResolveFailed(aServiceInfo, err);
+ } else {
+ aListener.onServiceResolved(result);
+ }
+ });
+ }
+};
diff --git a/netwerk/dns/mdns/libmdns/fallback/DNSPacket.jsm b/netwerk/dns/mdns/libmdns/fallback/DNSPacket.jsm
new file mode 100644
index 000000000..f0539fccb
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/fallback/DNSPacket.jsm
@@ -0,0 +1,297 @@
+/* -*- Mode: js; js-indent-level: 2; indent-tabs-mode: nil; tab-width: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+/* jshint esnext: true, moz: true */
+
+'use strict';
+
+this.EXPORTED_SYMBOLS = ['DNSPacket'];
+
+const { utils: Cu } = Components;
+
+Cu.import('resource://gre/modules/Services.jsm');
+
+Cu.import('resource://gre/modules/DataReader.jsm');
+Cu.import('resource://gre/modules/DataWriter.jsm');
+Cu.import('resource://gre/modules/DNSRecord.jsm');
+Cu.import('resource://gre/modules/DNSResourceRecord.jsm');
+
+const DEBUG = true;
+
+function debug(msg) {
+ Services.console.logStringMessage('DNSPacket: ' + msg);
+}
+
+let DNS_PACKET_SECTION_TYPES = [
+ 'QD', // Question
+ 'AN', // Answer
+ 'NS', // Authority
+ 'AR' // Additional
+];
+
+/**
+ * DNS Packet Structure
+ * *************************************************
+ *
+ * Header
+ * ======
+ *
+ * 00 2-Bytes 15
+ * -------------------------------------------------
+ * |00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
+ * -------------------------------------------------
+ * |<==================== ID =====================>|
+ * |QR|<== OP ===>|AA|TC|RD|RA|UN|AD|CD|<== RC ===>|
+ * |<================== QDCOUNT ==================>|
+ * |<================== ANCOUNT ==================>|
+ * |<================== NSCOUNT ==================>|
+ * |<================== ARCOUNT ==================>|
+ * -------------------------------------------------
+ *
+ * ID: 2-Bytes
+ * FLAGS: 2-Bytes
+ * - QR: 1-Bit
+ * - OP: 4-Bits
+ * - AA: 1-Bit
+ * - TC: 1-Bit
+ * - RD: 1-Bit
+ * - RA: 1-Bit
+ * - UN: 1-Bit
+ * - AD: 1-Bit
+ * - CD: 1-Bit
+ * - RC: 4-Bits
+ * QDCOUNT: 2-Bytes
+ * ANCOUNT: 2-Bytes
+ * NSCOUNT: 2-Bytes
+ * ARCOUNT: 2-Bytes
+ *
+ *
+ * Data
+ * ====
+ *
+ * 00 2-Bytes 15
+ * -------------------------------------------------
+ * |00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
+ * -------------------------------------------------
+ * |<???=============== QD[...] ===============???>|
+ * |<???=============== AN[...] ===============???>|
+ * |<???=============== NS[...] ===============???>|
+ * |<???=============== AR[...] ===============???>|
+ * -------------------------------------------------
+ *
+ * QD: ??-Bytes
+ * AN: ??-Bytes
+ * NS: ??-Bytes
+ * AR: ??-Bytes
+ *
+ *
+ * Question Record
+ * ===============
+ *
+ * 00 2-Bytes 15
+ * -------------------------------------------------
+ * |00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|
+ * -------------------------------------------------
+ * |<???================ NAME =================???>|
+ * |<=================== TYPE ====================>|
+ * |<=================== CLASS ===================>|
+ * -------------------------------------------------
+ *
+ * NAME: ??-Bytes
+ * TYPE: 2-Bytes
+ * CLASS: 2-Bytes
+ *
+ *
+ * Resource Record
+ * ===============
+ *
+ * 00 4-Bytes 31
+ * -------------------------------------------------
+ * |00|02|04|06|08|10|12|14|16|18|20|22|24|26|28|30|
+ * -------------------------------------------------
+ * |<???================ NAME =================???>|
+ * |<======= TYPE ========>|<======= CLASS =======>|
+ * |<==================== TTL ====================>|
+ * |<====== DATALEN ======>|<???==== DATA =====???>|
+ * -------------------------------------------------
+ *
+ * NAME: ??-Bytes
+ * TYPE: 2-Bytes
+ * CLASS: 2-Bytes
+ * DATALEN: 2-Bytes
+ * DATA: ??-Bytes (Specified By DATALEN)
+ */
+class DNSPacket {
+ constructor() {
+ this._flags = _valueToFlags(0x0000);
+ this._records = {};
+
+ DNS_PACKET_SECTION_TYPES.forEach((sectionType) => {
+ this._records[sectionType] = [];
+ });
+ }
+
+ static parse(data) {
+ let reader = new DataReader(data);
+ if (reader.getValue(2) !== 0x0000) {
+ throw new Error('Packet must start with 0x0000');
+ }
+
+ let packet = new DNSPacket();
+ packet._flags = _valueToFlags(reader.getValue(2));
+
+ let recordCounts = {};
+
+ // Parse the record counts.
+ DNS_PACKET_SECTION_TYPES.forEach((sectionType) => {
+ recordCounts[sectionType] = reader.getValue(2);
+ });
+
+ // Parse the actual records.
+ DNS_PACKET_SECTION_TYPES.forEach((sectionType) => {
+ let recordCount = recordCounts[sectionType];
+ for (let i = 0; i < recordCount; i++) {
+ if (sectionType === 'QD') {
+ packet.addRecord(sectionType,
+ DNSRecord.parseFromPacketReader(reader));
+ }
+
+ else {
+ packet.addRecord(sectionType,
+ DNSResourceRecord.parseFromPacketReader(reader));
+ }
+ }
+ });
+
+ if (!reader.eof) {
+ DEBUG && debug('Did not complete parsing packet data');
+ }
+
+ return packet;
+ }
+
+ getFlag(flag) {
+ return this._flags[flag];
+ }
+
+ setFlag(flag, value) {
+ this._flags[flag] = value;
+ }
+
+ addRecord(sectionType, record) {
+ this._records[sectionType].push(record);
+ }
+
+ getRecords(sectionTypes, recordType) {
+ let records = [];
+
+ sectionTypes.forEach((sectionType) => {
+ records = records.concat(this._records[sectionType]);
+ });
+
+ if (!recordType) {
+ return records;
+ }
+
+ return records.filter(r => r.recordType === recordType);
+ }
+
+ serialize() {
+ let writer = new DataWriter();
+
+ // Write leading 0x0000 (2 bytes)
+ writer.putValue(0x0000, 2);
+
+ // Write `flags` (2 bytes)
+ writer.putValue(_flagsToValue(this._flags), 2);
+
+ // Write lengths of record sections (2 bytes each)
+ DNS_PACKET_SECTION_TYPES.forEach((sectionType) => {
+ writer.putValue(this._records[sectionType].length, 2);
+ });
+
+ // Write records
+ DNS_PACKET_SECTION_TYPES.forEach((sectionType) => {
+ this._records[sectionType].forEach((record) => {
+ writer.putBytes(record.serialize());
+ });
+ });
+
+ return writer.data;
+ }
+
+ toJSON() {
+ return JSON.stringify(this.toJSONObject());
+ }
+
+ toJSONObject() {
+ let result = {flags: this._flags};
+ DNS_PACKET_SECTION_TYPES.forEach((sectionType) => {
+ result[sectionType] = [];
+
+ let records = this._records[sectionType];
+ records.forEach((record) => {
+ result[sectionType].push(record.toJSONObject());
+ });
+ });
+
+ return result;
+ }
+}
+
+/**
+ * @private
+ */
+function _valueToFlags(value) {
+ return {
+ QR: (value & 0x8000) >> 15,
+ OP: (value & 0x7800) >> 11,
+ AA: (value & 0x0400) >> 10,
+ TC: (value & 0x0200) >> 9,
+ RD: (value & 0x0100) >> 8,
+ RA: (value & 0x0080) >> 7,
+ UN: (value & 0x0040) >> 6,
+ AD: (value & 0x0020) >> 5,
+ CD: (value & 0x0010) >> 4,
+ RC: (value & 0x000f) >> 0
+ };
+}
+
+/**
+ * @private
+ */
+function _flagsToValue(flags) {
+ let value = 0x0000;
+
+ value += flags.QR & 0x01;
+
+ value <<= 4;
+ value += flags.OP & 0x0f;
+
+ value <<= 1;
+ value += flags.AA & 0x01;
+
+ value <<= 1;
+ value += flags.TC & 0x01;
+
+ value <<= 1;
+ value += flags.RD & 0x01;
+
+ value <<= 1;
+ value += flags.RA & 0x01;
+
+ value <<= 1;
+ value += flags.UN & 0x01;
+
+ value <<= 1;
+ value += flags.AD & 0x01;
+
+ value <<= 1;
+ value += flags.CD & 0x01;
+
+ value <<= 4;
+ value += flags.RC & 0x0f;
+
+ return value;
+}
diff --git a/netwerk/dns/mdns/libmdns/fallback/DNSRecord.jsm b/netwerk/dns/mdns/libmdns/fallback/DNSRecord.jsm
new file mode 100644
index 000000000..f5d48731f
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/fallback/DNSRecord.jsm
@@ -0,0 +1,70 @@
+/* -*- Mode: js; js-indent-level: 2; indent-tabs-mode: nil; tab-width: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+/* jshint esnext: true, moz: true */
+
+'use strict';
+
+this.EXPORTED_SYMBOLS = ['DNSRecord'];
+
+const { utils: Cu } = Components;
+
+Cu.import('resource://gre/modules/DataWriter.jsm');
+Cu.import('resource://gre/modules/DNSTypes.jsm');
+
+class DNSRecord {
+ constructor(properties = {}) {
+ this.name = properties.name || '';
+ this.recordType = properties.recordType || DNS_RECORD_TYPES.ANY;
+ this.classCode = properties.classCode || DNS_CLASS_CODES.IN;
+ this.cacheFlush = properties.cacheFlush || false;
+ }
+
+ static parseFromPacketReader(reader) {
+ let name = reader.getLabel();
+ let recordType = reader.getValue(2);
+ let classCode = reader.getValue(2);
+ let cacheFlush = (classCode & 0x8000) ? true : false;
+ classCode &= 0xff;
+
+ return new this({
+ name: name,
+ recordType: recordType,
+ classCode: classCode,
+ cacheFlush: cacheFlush
+ });
+ }
+
+ serialize() {
+ let writer = new DataWriter();
+
+ // Write `name` (ends with trailing 0x00 byte)
+ writer.putLabel(this.name);
+
+ // Write `recordType` (2 bytes)
+ writer.putValue(this.recordType, 2);
+
+ // Write `classCode` (2 bytes)
+ let classCode = this.classCode;
+ if (this.cacheFlush) {
+ classCode |= 0x8000;
+ }
+ writer.putValue(classCode, 2);
+
+ return writer.data;
+ }
+
+ toJSON() {
+ return JSON.stringify(this.toJSONObject());
+ }
+
+ toJSONObject() {
+ return {
+ name: this.name,
+ recordType: this.recordType,
+ classCode: this.classCode,
+ cacheFlush: this.cacheFlush
+ };
+ }
+}
diff --git a/netwerk/dns/mdns/libmdns/fallback/DNSResourceRecord.jsm b/netwerk/dns/mdns/libmdns/fallback/DNSResourceRecord.jsm
new file mode 100644
index 000000000..ba0072a50
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/fallback/DNSResourceRecord.jsm
@@ -0,0 +1,221 @@
+/* -*- Mode: js; js-indent-level: 2; indent-tabs-mode: nil; tab-width: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+/* jshint esnext: true, moz: true */
+
+'use strict';
+
+this.EXPORTED_SYMBOLS = ['DNSResourceRecord'];
+
+const { utils: Cu } = Components;
+
+Cu.import('resource://gre/modules/Services.jsm');
+Cu.import('resource://gre/modules/DataReader.jsm');
+Cu.import('resource://gre/modules/DataWriter.jsm');
+Cu.import('resource://gre/modules/DNSRecord.jsm');
+Cu.import('resource://gre/modules/DNSTypes.jsm');
+
+function debug(msg) {
+ Services.console.logStringMessage('MulticastDNS: ' + msg);
+}
+
+const DNS_RESOURCE_RECORD_DEFAULT_TTL = 120; // 120 seconds
+
+class DNSResourceRecord extends DNSRecord {
+ constructor(properties = {}) {
+ super(properties);
+
+ this.ttl = properties.ttl || DNS_RESOURCE_RECORD_DEFAULT_TTL;
+ this.data = properties.data || {};
+ }
+
+ static parseFromPacketReader(reader) {
+ let record = super.parseFromPacketReader(reader);
+
+ let ttl = reader.getValue(4);
+ let recordData = reader.getBytes(reader.getValue(2));
+ let packetData = reader.data;
+
+ let data;
+
+ switch (record.recordType) {
+ case DNS_RECORD_TYPES.A:
+ data = _parseA(recordData, packetData);
+ break;
+ case DNS_RECORD_TYPES.PTR:
+ data = _parsePTR(recordData, packetData);
+ break;
+ case DNS_RECORD_TYPES.TXT:
+ data = _parseTXT(recordData, packetData);
+ break;
+ case DNS_RECORD_TYPES.SRV:
+ data = _parseSRV(recordData, packetData);
+ break;
+ default:
+ data = null;
+ break;
+ }
+
+ record.ttl = ttl;
+ record.data = data;
+
+ return record;
+ }
+
+ serialize() {
+ let writer = new DataWriter(super.serialize());
+
+ // Write `ttl` (4 bytes)
+ writer.putValue(this.ttl, 4);
+
+ let data;
+
+ switch (this.recordType) {
+ case DNS_RECORD_TYPES.A:
+ data = _serializeA(this.data);
+ break;
+ case DNS_RECORD_TYPES.PTR:
+ data = _serializePTR(this.data);
+ break;
+ case DNS_RECORD_TYPES.TXT:
+ data = _serializeTXT(this.data);
+ break;
+ case DNS_RECORD_TYPES.SRV:
+ data = _serializeSRV(this.data);
+ break;
+ default:
+ data = new Uint8Array();
+ break;
+ }
+
+ // Write `data` length.
+ writer.putValue(data.length, 2);
+
+ // Write `data` (ends with trailing 0x00 byte)
+ writer.putBytes(data);
+
+ return writer.data;
+ }
+
+ toJSON() {
+ return JSON.stringify(this.toJSONObject());
+ }
+
+ toJSONObject() {
+ let result = super.toJSONObject();
+ result.ttl = this.ttl;
+ result.data = this.data;
+ return result;
+ }
+}
+
+/**
+ * @private
+ */
+function _parseA(recordData, packetData) {
+ let reader = new DataReader(recordData);
+
+ let parts = [];
+ for (let i = 0; i < 4; i++) {
+ parts.push(reader.getValue(1));
+ }
+
+ return parts.join('.');
+}
+
+/**
+ * @private
+ */
+function _parsePTR(recordData, packetData) {
+ let reader = new DataReader(recordData);
+
+ return reader.getLabel(packetData);
+}
+
+/**
+ * @private
+ */
+function _parseTXT(recordData, packetData) {
+ let reader = new DataReader(recordData);
+
+ let result = {};
+
+ let label = reader.getLabel(packetData);
+ if (label.length > 0) {
+ let parts = label.split('.');
+ parts.forEach((part) => {
+ let [name] = part.split('=', 1);
+ let value = part.substr(name.length + 1);
+ result[name] = value;
+ });
+ }
+
+ return result;
+}
+
+/**
+ * @private
+ */
+function _parseSRV(recordData, packetData) {
+ let reader = new DataReader(recordData);
+
+ let priority = reader.getValue(2);
+ let weight = reader.getValue(2);
+ let port = reader.getValue(2);
+ let target = reader.getLabel(packetData);
+
+ return { priority, weight, port, target };
+}
+
+/**
+ * @private
+ */
+function _serializeA(data) {
+ let writer = new DataWriter();
+
+ let parts = data.split('.');
+ for (let i = 0; i < 4; i++) {
+ writer.putValue(parseInt(parts[i], 10) || 0);
+ }
+
+ return writer.data;
+}
+
+/**
+ * @private
+ */
+function _serializePTR(data) {
+ let writer = new DataWriter();
+
+ writer.putLabel(data);
+
+ return writer.data;
+}
+
+/**
+ * @private
+ */
+function _serializeTXT(data) {
+ let writer = new DataWriter();
+
+ for (let name in data) {
+ writer.putLengthString(name + '=' + data[name]);
+ }
+
+ return writer.data;
+}
+
+/**
+ * @private
+ */
+function _serializeSRV(data) {
+ let writer = new DataWriter();
+
+ writer.putValue(data.priority || 0, 2);
+ writer.putValue(data.weight || 0, 2);
+ writer.putValue(data.port || 0, 2);
+ writer.putLabel(data.target);
+
+ return writer.data;
+}
diff --git a/netwerk/dns/mdns/libmdns/fallback/DNSTypes.jsm b/netwerk/dns/mdns/libmdns/fallback/DNSTypes.jsm
new file mode 100644
index 000000000..8c5470639
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/fallback/DNSTypes.jsm
@@ -0,0 +1,100 @@
+/* -*- Mode: js; js-indent-level: 2; indent-tabs-mode: nil; tab-width: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+/* jshint esnext: true, moz: true */
+
+'use strict';
+
+this.EXPORTED_SYMBOLS = [
+ 'DNS_QUERY_RESPONSE_CODES',
+ 'DNS_AUTHORITATIVE_ANSWER_CODES',
+ 'DNS_CLASS_CODES',
+ 'DNS_RECORD_TYPES'
+];
+
+let DNS_QUERY_RESPONSE_CODES = {
+ QUERY : 0, // RFC 1035 - Query
+ RESPONSE : 1 // RFC 1035 - Reponse
+};
+
+let DNS_AUTHORITATIVE_ANSWER_CODES = {
+ NO : 0, // RFC 1035 - Not Authoritative
+ YES : 1 // RFC 1035 - Is Authoritative
+};
+
+let DNS_CLASS_CODES = {
+ IN : 0x01, // RFC 1035 - Internet
+ CS : 0x02, // RFC 1035 - CSNET
+ CH : 0x03, // RFC 1035 - CHAOS
+ HS : 0x04, // RFC 1035 - Hesiod
+ NONE : 0xfe, // RFC 2136 - None
+ ANY : 0xff, // RFC 1035 - Any
+};
+
+let DNS_RECORD_TYPES = {
+ SIGZERO : 0, // RFC 2931
+ A : 1, // RFC 1035
+ NS : 2, // RFC 1035
+ MD : 3, // RFC 1035
+ MF : 4, // RFC 1035
+ CNAME : 5, // RFC 1035
+ SOA : 6, // RFC 1035
+ MB : 7, // RFC 1035
+ MG : 8, // RFC 1035
+ MR : 9, // RFC 1035
+ NULL : 10, // RFC 1035
+ WKS : 11, // RFC 1035
+ PTR : 12, // RFC 1035
+ HINFO : 13, // RFC 1035
+ MINFO : 14, // RFC 1035
+ MX : 15, // RFC 1035
+ TXT : 16, // RFC 1035
+ RP : 17, // RFC 1183
+ AFSDB : 18, // RFC 1183
+ X25 : 19, // RFC 1183
+ ISDN : 20, // RFC 1183
+ RT : 21, // RFC 1183
+ NSAP : 22, // RFC 1706
+ NSAP_PTR : 23, // RFC 1348
+ SIG : 24, // RFC 2535
+ KEY : 25, // RFC 2535
+ PX : 26, // RFC 2163
+ GPOS : 27, // RFC 1712
+ AAAA : 28, // RFC 1886
+ LOC : 29, // RFC 1876
+ NXT : 30, // RFC 2535
+ EID : 31, // RFC ????
+ NIMLOC : 32, // RFC ????
+ SRV : 33, // RFC 2052
+ ATMA : 34, // RFC ????
+ NAPTR : 35, // RFC 2168
+ KX : 36, // RFC 2230
+ CERT : 37, // RFC 2538
+ DNAME : 39, // RFC 2672
+ OPT : 41, // RFC 2671
+ APL : 42, // RFC 3123
+ DS : 43, // RFC 4034
+ SSHFP : 44, // RFC 4255
+ IPSECKEY : 45, // RFC 4025
+ RRSIG : 46, // RFC 4034
+ NSEC : 47, // RFC 4034
+ DNSKEY : 48, // RFC 4034
+ DHCID : 49, // RFC 4701
+ NSEC3 : 50, // RFC ????
+ NSEC3PARAM : 51, // RFC ????
+ HIP : 55, // RFC 5205
+ SPF : 99, // RFC 4408
+ UINFO : 100, // RFC ????
+ UID : 101, // RFC ????
+ GID : 102, // RFC ????
+ UNSPEC : 103, // RFC ????
+ TKEY : 249, // RFC 2930
+ TSIG : 250, // RFC 2931
+ IXFR : 251, // RFC 1995
+ AXFR : 252, // RFC 1035
+ MAILB : 253, // RFC 1035
+ MAILA : 254, // RFC 1035
+ ANY : 255, // RFC 1035
+ DLV : 32769 // RFC 4431
+};
diff --git a/netwerk/dns/mdns/libmdns/fallback/DataReader.jsm b/netwerk/dns/mdns/libmdns/fallback/DataReader.jsm
new file mode 100644
index 000000000..a20c1dc32
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/fallback/DataReader.jsm
@@ -0,0 +1,133 @@
+/* -*- Mode: js; js-indent-level: 2; indent-tabs-mode: nil; tab-width: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+/* jshint esnext: true, moz: true */
+
+'use strict';
+
+this.EXPORTED_SYMBOLS = ['DataReader'];
+
+class DataReader {
+ // `data` is `Uint8Array`
+ constructor(data, startByte = 0) {
+ this._data = data;
+ this._cursor = startByte;
+ }
+
+ get buffer() {
+ return this._data.buffer;
+ }
+
+ get data() {
+ return this._data;
+ }
+
+ get eof() {
+ return this._cursor >= this._data.length;
+ }
+
+ getBytes(length = 1) {
+ if (!length) {
+ return new Uint8Array();
+ }
+
+ let end = this._cursor + length;
+ if (end > this._data.length) {
+ return new Uint8Array();
+ }
+
+ let uint8Array = new Uint8Array(this.buffer.slice(this._cursor, end));
+ this._cursor += length;
+
+ return uint8Array;
+ }
+
+ getString(length) {
+ let uint8Array = this.getBytes(length);
+ return _uint8ArrayToString(uint8Array);
+ }
+
+ getValue(length) {
+ let uint8Array = this.getBytes(length);
+ return _uint8ArrayToValue(uint8Array);
+ }
+
+ getLabel(decompressData) {
+ let parts = [];
+ let partLength;
+
+ while ((partLength = this.getValue(1))) {
+ // If a length has been specified instead of a pointer,
+ // read the string of the specified length.
+ if (partLength !== 0xc0) {
+ parts.push(this.getString(partLength));
+ continue;
+ }
+
+ // TODO: Handle case where we have a pointer to the label
+ parts.push(String.fromCharCode(0xc0) + this.getString(1));
+ break;
+ }
+
+ let label = parts.join('.');
+
+ return _decompressLabel(label, decompressData || this._data);
+ }
+}
+
+/**
+ * @private
+ */
+function _uint8ArrayToValue(uint8Array) {
+ let length = uint8Array.length;
+ if (length === 0) {
+ return null;
+ }
+
+ let value = 0;
+ for (let i = 0; i < length; i++) {
+ value = value << 8;
+ value += uint8Array[i];
+ }
+
+ return value;
+}
+
+/**
+ * @private
+ */
+function _uint8ArrayToString(uint8Array) {
+ let length = uint8Array.length;
+ if (length === 0) {
+ return '';
+ }
+
+ let results = [];
+ for (let i = 0; i < length; i += 1024) {
+ results.push(String.fromCharCode.apply(null, uint8Array.subarray(i, i + 1024)));
+ }
+
+ return results.join('');
+}
+
+/**
+ * @private
+ */
+function _decompressLabel(label, decompressData) {
+ let result = '';
+
+ for (let i = 0, length = label.length; i < length; i++) {
+ if (label.charCodeAt(i) !== 0xc0) {
+ result += label.charAt(i);
+ continue;
+ }
+
+ i++;
+
+ let reader = new DataReader(decompressData, label.charCodeAt(i));
+ result += _decompressLabel(reader.getLabel(), decompressData);
+ }
+
+ return result;
+}
diff --git a/netwerk/dns/mdns/libmdns/fallback/DataWriter.jsm b/netwerk/dns/mdns/libmdns/fallback/DataWriter.jsm
new file mode 100644
index 000000000..af20d65f5
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/fallback/DataWriter.jsm
@@ -0,0 +1,98 @@
+/* -*- Mode: js; js-indent-level: 2; indent-tabs-mode: nil; tab-width: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+/* jshint esnext: true, moz: true */
+
+'use strict';
+
+this.EXPORTED_SYMBOLS = ['DataWriter'];
+
+class DataWriter {
+ constructor(data, maxBytes = 512) {
+ if (typeof data === 'number') {
+ maxBytes = data;
+ data = undefined;
+ }
+
+ this._buffer = new ArrayBuffer(maxBytes);
+ this._data = new Uint8Array(this._buffer);
+ this._cursor = 0;
+
+ if (data) {
+ this.putBytes(data);
+ }
+ }
+
+ get buffer() {
+ return this._buffer.slice(0, this._cursor);
+ }
+
+ get data() {
+ return new Uint8Array(this.buffer);
+ }
+
+ // `data` is `Uint8Array`
+ putBytes(data) {
+ if (this._cursor + data.length > this._data.length) {
+ throw new Error('DataWriter buffer is exceeded');
+ }
+
+ for (let i = 0, length = data.length; i < length; i++) {
+ this._data[this._cursor] = data[i];
+ this._cursor++;
+ }
+ }
+
+ putByte(byte) {
+ if (this._cursor + 1 > this._data.length) {
+ throw new Error('DataWriter buffer is exceeded');
+ }
+
+ this._data[this._cursor] = byte
+ this._cursor++;
+ }
+
+ putValue(value, length) {
+ length = length || 1;
+ if (length == 1) {
+ this.putByte(value);
+ } else {
+ this.putBytes(_valueToUint8Array(value, length));
+ }
+ }
+
+ putLabel(label) {
+ // Eliminate any trailing '.'s in the label (valid in text representation).
+ label = label.replace(/\.$/, '');
+ let parts = label.split('.');
+ parts.forEach((part) => {
+ this.putLengthString(part);
+ });
+ this.putValue(0);
+ }
+
+ putLengthString(string) {
+ if (string.length > 0xff) {
+ throw new Error("String too long.");
+ }
+ this.putValue(string.length);
+ for (let i = 0; i < string.length; i++) {
+ this.putValue(string.charCodeAt(i));
+ }
+ }
+}
+
+/**
+ * @private
+ */
+function _valueToUint8Array(value, length) {
+ let arrayBuffer = new ArrayBuffer(length);
+ let uint8Array = new Uint8Array(arrayBuffer);
+ for (let i = length - 1; i >= 0; i--) {
+ uint8Array[i] = value & 0xff;
+ value = value >> 8;
+ }
+
+ return uint8Array;
+}
diff --git a/netwerk/dns/mdns/libmdns/fallback/MulticastDNS.jsm b/netwerk/dns/mdns/libmdns/fallback/MulticastDNS.jsm
new file mode 100644
index 000000000..f43dfd5f8
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/fallback/MulticastDNS.jsm
@@ -0,0 +1,875 @@
+/* -*- Mode: js; js-indent-level: 2; indent-tabs-mode: nil; tab-width: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+/* jshint esnext: true, moz: true */
+
+'use strict';
+
+this.EXPORTED_SYMBOLS = ['MulticastDNS'];
+
+const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
+
+Cu.import('resource://gre/modules/Services.jsm');
+Cu.import('resource://gre/modules/Timer.jsm');
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+
+Cu.import('resource://gre/modules/DNSPacket.jsm');
+Cu.import('resource://gre/modules/DNSRecord.jsm');
+Cu.import('resource://gre/modules/DNSResourceRecord.jsm');
+Cu.import('resource://gre/modules/DNSTypes.jsm');
+
+const NS_NETWORK_LINK_TOPIC = 'network:link-status-changed';
+
+let observerService = Cc["@mozilla.org/observer-service;1"]
+ .getService(Components.interfaces.nsIObserverService);
+let networkInfoService = Cc['@mozilla.org/network-info-service;1']
+ .createInstance(Ci.nsINetworkInfoService);
+
+const DEBUG = true;
+
+const MDNS_MULTICAST_GROUP = '224.0.0.251';
+const MDNS_PORT = 5353;
+const DEFAULT_TTL = 120;
+
+function debug(msg) {
+ dump('MulticastDNS: ' + msg + '\n');
+}
+
+function ServiceKey(svc) {
+ return "" + svc.serviceType.length + "/" + svc.serviceType + "|" +
+ svc.serviceName.length + "/" + svc.serviceName + "|" +
+ svc.port;
+}
+
+function TryGet(obj, name) {
+ try {
+ return obj[name];
+ } catch (err) {
+ return undefined;
+ }
+}
+
+function IsIpv4Address(addr) {
+ let parts = addr.split('.');
+ if (parts.length != 4) {
+ return false;
+ }
+ for (let part of parts) {
+ let partInt = Number.parseInt(part, 10);
+ if (partInt.toString() != part) {
+ return false;
+ }
+ if (partInt < 0 || partInt >= 256) {
+ return false;
+ }
+ }
+ return true;
+}
+
+class PublishedService {
+ constructor(attrs) {
+ this.serviceType = attrs.serviceType.replace(/\.$/, '');
+ this.serviceName = attrs.serviceName;
+ this.domainName = TryGet(attrs, 'domainName') || "local";
+ this.address = TryGet(attrs, 'address') || "0.0.0.0";
+ this.port = attrs.port;
+ this.serviceAttrs = _propertyBagToObject(TryGet(attrs, 'attributes') || {});
+ this.host = TryGet(attrs, 'host');
+ this.key = this.generateKey();
+ this.lastAdvertised = undefined;
+ this.advertiseTimer = undefined;
+ }
+
+ equals(svc) {
+ return (this.port == svc.port) &&
+ (this.serviceName == svc.serviceName) &&
+ (this.serviceType == svc.serviceType);
+ }
+
+ generateKey() {
+ return ServiceKey(this);
+ }
+
+ ptrMatch(name) {
+ return name == (this.serviceType + "." + this.domainName);
+ }
+
+ clearAdvertiseTimer() {
+ if (!this.advertiseTimer) {
+ return;
+ }
+ clearTimeout(this.advertiseTimer);
+ this.advertiseTimer = undefined;
+ }
+}
+
+class MulticastDNS {
+ constructor() {
+ this._listeners = new Map();
+ this._sockets = new Map();
+ this._services = new Map();
+ this._discovered = new Map();
+ this._querySocket = undefined;
+ this._broadcastReceiverSocket = undefined;
+ this._broadcastTimer = undefined;
+
+ this._networkLinkObserver = {
+ observe: (subject, topic, data) => {
+ DEBUG && debug(NS_NETWORK_LINK_TOPIC + '(' + data + '); Clearing list of previously discovered services');
+ this._discovered.clear();
+ }
+ };
+ }
+
+ _attachNetworkLinkObserver() {
+ if (this._networkLinkObserverTimeout) {
+ clearTimeout(this._networkLinkObserverTimeout);
+ }
+
+ if (!this._isNetworkLinkObserverAttached) {
+ DEBUG && debug('Attaching observer ' + NS_NETWORK_LINK_TOPIC);
+ observerService.addObserver(this._networkLinkObserver, NS_NETWORK_LINK_TOPIC, false);
+ this._isNetworkLinkObserverAttached = true;
+ }
+ }
+
+ _detachNetworkLinkObserver() {
+ if (this._isNetworkLinkObserverAttached) {
+ if (this._networkLinkObserverTimeout) {
+ clearTimeout(this._networkLinkObserverTimeout);
+ }
+
+ this._networkLinkObserverTimeout = setTimeout(() => {
+ DEBUG && debug('Detaching observer ' + NS_NETWORK_LINK_TOPIC);
+ observerService.removeObserver(this._networkLinkObserver, NS_NETWORK_LINK_TOPIC);
+ this._isNetworkLinkObserverAttached = false;
+ this._networkLinkObserverTimeout = null;
+ }, 5000);
+ }
+ }
+
+ startDiscovery(aServiceType, aListener) {
+ DEBUG && debug('startDiscovery("' + aServiceType + '")');
+ let { serviceType } = _parseServiceDomainName(aServiceType);
+
+ this._attachNetworkLinkObserver();
+ this._addServiceListener(serviceType, aListener);
+
+ try {
+ this._query(serviceType + '.local');
+ aListener.onDiscoveryStarted(serviceType);
+ } catch (e) {
+ DEBUG && debug('startDiscovery("' + serviceType + '") FAILED: ' + e);
+ this._removeServiceListener(serviceType, aListener);
+ aListener.onStartDiscoveryFailed(serviceType, Cr.NS_ERROR_FAILURE);
+ }
+ }
+
+ stopDiscovery(aServiceType, aListener) {
+ DEBUG && debug('stopDiscovery("' + aServiceType + '")');
+ let { serviceType } = _parseServiceDomainName(aServiceType);
+
+ this._detachNetworkLinkObserver();
+ this._removeServiceListener(serviceType, aListener);
+
+ aListener.onDiscoveryStopped(serviceType);
+
+ this._checkCloseSockets();
+ }
+
+ resolveService(aServiceInfo, aListener) {
+ DEBUG && debug('resolveService(): ' + aServiceInfo.serviceName);
+
+ // Address info is already resolved during discovery
+ setTimeout(() => aListener.onServiceResolved(aServiceInfo));
+ }
+
+ registerService(aServiceInfo, aListener) {
+ DEBUG && debug('registerService(): ' + aServiceInfo.serviceName);
+
+ // Initialize the broadcast receiver socket in case it
+ // hasn't already been started so we can listen for
+ // multicast queries/announcements on all interfaces.
+ this._getBroadcastReceiverSocket();
+
+ for (let name of ['port', 'serviceName', 'serviceType']) {
+ if (!TryGet(aServiceInfo, name)) {
+ aListener.onRegistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE);
+ throw new Error('Invalid nsIDNSServiceInfo; Missing "' + name + '"');
+ }
+ }
+
+ let publishedService;
+ try {
+ publishedService = new PublishedService(aServiceInfo);
+ } catch (e) {
+ DEBUG && debug("Error constructing PublishedService: " + e + " - " + e.stack);
+ setTimeout(() => aListener.onRegistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE));
+ return;
+ }
+
+ // Ensure such a service does not already exist.
+ if (this._services.get(publishedService.key)) {
+ setTimeout(() => aListener.onRegistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE));
+ return;
+ }
+
+ // Make sure that the service addr is '0.0.0.0', or there is at least one
+ // socket open on the address the service is open on.
+ this._getSockets().then((sockets) => {
+ if (publishedService.address != '0.0.0.0' && !sockets.get(publishedService.address)) {
+ setTimeout(() => aListener.onRegistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE));
+ return;
+ }
+
+ this._services.set(publishedService.key, publishedService);
+
+ // Service registered.. call onServiceRegistered on next tick.
+ setTimeout(() => aListener.onServiceRegistered(aServiceInfo));
+
+ // Set a timeout to start advertising the service too.
+ publishedService.advertiseTimer = setTimeout(() => {
+ this._advertiseService(publishedService.key, /* firstAdv = */ true);
+ });
+ });
+ }
+
+ unregisterService(aServiceInfo, aListener) {
+ DEBUG && debug('unregisterService(): ' + aServiceInfo.serviceName);
+
+ let serviceKey;
+ try {
+ serviceKey = ServiceKey(aServiceInfo);
+ } catch (e) {
+ setTimeout(() => aListener.onUnregistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE));
+ return;
+ }
+
+ let publishedService = this._services.get(serviceKey);
+ if (!publishedService) {
+ setTimeout(() => aListener.onUnregistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE));
+ return;
+ }
+
+ // Clear any advertise timeout for this published service.
+ publishedService.clearAdvertiseTimer();
+
+ // Delete the service from the service map.
+ if (!this._services.delete(serviceKey)) {
+ setTimeout(() => aListener.onUnregistrationFailed(aServiceInfo, Cr.NS_ERROR_FAILURE));
+ return;
+ }
+
+ // Check the broadcast timer again to rejig when it should run next.
+ this._checkStartBroadcastTimer();
+
+ // Check to see if sockets should be closed, and if so close them.
+ this._checkCloseSockets();
+
+ aListener.onServiceUnregistered(aServiceInfo);
+ }
+
+ _respondToQuery(serviceKey, message) {
+ let address = message.fromAddr.address;
+ let port = message.fromAddr.port;
+ DEBUG && debug('_respondToQuery(): key=' + serviceKey + ', fromAddr='
+ + address + ":" + port);
+
+ let publishedService = this._services.get(serviceKey);
+ if (!publishedService) {
+ debug("_respondToQuery Could not find service (key=" + serviceKey + ")");
+ return;
+ }
+
+ DEBUG && debug('_respondToQuery(): key=' + serviceKey + ': SENDING RESPONSE');
+ this._advertiseServiceHelper(publishedService, {address,port});
+ }
+
+ _advertiseService(serviceKey, firstAdv) {
+ DEBUG && debug('_advertiseService(): key=' + serviceKey);
+ let publishedService = this._services.get(serviceKey);
+ if (!publishedService) {
+ debug("_advertiseService Could not find service to advertise (key=" + serviceKey + ")");
+ return;
+ }
+
+ publishedService.advertiseTimer = undefined;
+
+ this._advertiseServiceHelper(publishedService, null).then(() => {
+ // If first advertisement, re-advertise in 1 second.
+ // Otherwise, set the lastAdvertised time.
+ if (firstAdv) {
+ publishedService.advertiseTimer = setTimeout(() => {
+ this._advertiseService(serviceKey)
+ }, 1000);
+ } else {
+ publishedService.lastAdvertised = Date.now();
+ this._checkStartBroadcastTimer();
+ }
+ });
+ }
+
+ _advertiseServiceHelper(svc, target) {
+ if (!target) {
+ target = {address:MDNS_MULTICAST_GROUP, port:MDNS_PORT};
+ }
+
+ return this._getSockets().then((sockets) => {
+ sockets.forEach((socket, address) => {
+ if (svc.address == "0.0.0.0" || address == svc.address)
+ {
+ let packet = this._makeServicePacket(svc, [address]);
+ let data = packet.serialize();
+ try {
+ socket.send(target.address, target.port, data, data.length);
+ } catch (err) {
+ DEBUG && debug("Failed to send packet to "
+ + target.address + ":" + target.port);
+ }
+ }
+ });
+ });
+ }
+
+ _cancelBroadcastTimer() {
+ if (!this._broadcastTimer) {
+ return;
+ }
+ clearTimeout(this._broadcastTimer);
+ this._broadcastTimer = undefined;
+ }
+
+ _checkStartBroadcastTimer() {
+ DEBUG && debug("_checkStartBroadcastTimer()");
+ // Cancel any existing broadcasting timer.
+ this._cancelBroadcastTimer();
+
+ let now = Date.now();
+
+ // Go through services and find services to broadcast.
+ let bcastServices = [];
+ let nextBcastWait = undefined;
+ for (let [serviceKey, publishedService] of this._services) {
+ // if lastAdvertised is undefined, service hasn't finished it's initial
+ // two broadcasts.
+ if (publishedService.lastAdvertised === undefined) {
+ continue;
+ }
+
+ // Otherwise, check lastAdvertised against now.
+ let msSinceAdv = now - publishedService.lastAdvertised;
+
+ // If msSinceAdv is more than 90% of the way to the TTL, advertise now.
+ if (msSinceAdv > (DEFAULT_TTL * 1000 * 0.9)) {
+ bcastServices.push(publishedService);
+ continue;
+ }
+
+ // Otherwise, calculate the next time to advertise for this service.
+ // We set that at 95% of the time to the TTL expiry.
+ let nextAdvWait = (DEFAULT_TTL * 1000 * 0.95) - msSinceAdv;
+ if (nextBcastWait === undefined || nextBcastWait > nextAdvWait) {
+ nextBcastWait = nextAdvWait;
+ }
+ }
+
+ // Schedule an immediate advertisement of all services to be advertised now.
+ for (let svc of bcastServices) {
+ svc.advertiseTimer = setTimeout(() => this._advertiseService(svc.key));
+ }
+
+ // Schedule next broadcast check for the next bcast time.
+ if (nextBcastWait !== undefined) {
+ DEBUG && debug("_checkStartBroadcastTimer(): Scheduling next check in " + nextBcastWait + "ms");
+ this._broadcastTimer = setTimeout(() => this._checkStartBroadcastTimer(), nextBcastWait);
+ }
+ }
+
+ _query(name) {
+ DEBUG && debug('query("' + name + '")');
+ let packet = new DNSPacket();
+ packet.setFlag('QR', DNS_QUERY_RESPONSE_CODES.QUERY);
+
+ // PTR Record
+ packet.addRecord('QD', new DNSRecord({
+ name: name,
+ recordType: DNS_RECORD_TYPES.PTR,
+ classCode: DNS_CLASS_CODES.IN,
+ cacheFlush: true
+ }));
+
+ let data = packet.serialize();
+
+ // Initialize the broadcast receiver socket in case it
+ // hasn't already been started so we can listen for
+ // multicast queries/announcements on all interfaces.
+ this._getBroadcastReceiverSocket();
+
+ this._getQuerySocket().then((querySocket) => {
+ DEBUG && debug('sending query on query socket ("' + name + '")');
+ querySocket.send(MDNS_MULTICAST_GROUP, MDNS_PORT, data, data.length);
+ });
+
+ // Automatically announce previously-discovered
+ // services that match and haven't expired yet.
+ setTimeout(() => {
+ DEBUG && debug('announcing previously discovered services ("' + name + '")');
+ let { serviceType } = _parseServiceDomainName(name);
+
+ this._clearExpiredDiscoveries();
+ this._discovered.forEach((discovery, key) => {
+ let serviceInfo = discovery.serviceInfo;
+ if (serviceInfo.serviceType !== serviceType) {
+ return;
+ }
+
+ let listeners = this._listeners.get(serviceInfo.serviceType) || [];
+ listeners.forEach((listener) => {
+ listener.onServiceFound(serviceInfo);
+ });
+ });
+ });
+ }
+
+ _clearExpiredDiscoveries() {
+ this._discovered.forEach((discovery, key) => {
+ if (discovery.expireTime < Date.now()) {
+ this._discovered.delete(key);
+ return;
+ }
+ });
+ }
+
+ _handleQueryPacket(packet, message) {
+ packet.getRecords(['QD']).forEach((record) => {
+ // Don't respond if the query's class code is not IN or ANY.
+ if (record.classCode !== DNS_CLASS_CODES.IN &&
+ record.classCode !== DNS_CLASS_CODES.ANY) {
+ return;
+ }
+
+ // Don't respond if the query's record type is not PTR or ANY.
+ if (record.recordType !== DNS_RECORD_TYPES.PTR &&
+ record.recordType !== DNS_RECORD_TYPES.ANY) {
+ return;
+ }
+
+ for (let [serviceKey, publishedService] of this._services) {
+ DEBUG && debug("_handleQueryPacket: " + packet.toJSON());
+ if (publishedService.ptrMatch(record.name)) {
+ this._respondToQuery(serviceKey, message);
+ }
+ }
+ });
+ }
+
+ _makeServicePacket(service, addresses) {
+ let packet = new DNSPacket();
+ packet.setFlag('QR', DNS_QUERY_RESPONSE_CODES.RESPONSE);
+ packet.setFlag('AA', DNS_AUTHORITATIVE_ANSWER_CODES.YES);
+
+ let host = service.host || _hostname;
+
+ // e.g.: foo-bar-service._http._tcp.local
+ let serviceDomainName = service.serviceName + '.' + service.serviceType + '.local';
+
+ // PTR Record
+ packet.addRecord('AN', new DNSResourceRecord({
+ name: service.serviceType + '.local', // e.g.: _http._tcp.local
+ recordType: DNS_RECORD_TYPES.PTR,
+ data: serviceDomainName
+ }));
+
+ // SRV Record
+ packet.addRecord('AR', new DNSResourceRecord({
+ name: serviceDomainName,
+ recordType: DNS_RECORD_TYPES.SRV,
+ classCode: DNS_CLASS_CODES.IN,
+ cacheFlush: true,
+ data: {
+ priority: 0,
+ weight: 0,
+ port: service.port,
+ target: host // e.g.: My-Android-Phone.local
+ }
+ }));
+
+ // A Records
+ for (let address of addresses) {
+ packet.addRecord('AR', new DNSResourceRecord({
+ name: host,
+ recordType: DNS_RECORD_TYPES.A,
+ data: address
+ }));
+ }
+
+ // TXT Record
+ packet.addRecord('AR', new DNSResourceRecord({
+ name: serviceDomainName,
+ recordType: DNS_RECORD_TYPES.TXT,
+ classCode: DNS_CLASS_CODES.IN,
+ cacheFlush: true,
+ data: service.serviceAttrs || {}
+ }));
+
+ return packet;
+ }
+
+ _handleResponsePacket(packet, message) {
+ let services = {};
+ let hosts = {};
+
+ let srvRecords = packet.getRecords(['AN', 'AR'], DNS_RECORD_TYPES.SRV);
+ let txtRecords = packet.getRecords(['AN', 'AR'], DNS_RECORD_TYPES.TXT);
+ let ptrRecords = packet.getRecords(['AN', 'AR'], DNS_RECORD_TYPES.PTR);
+ let aRecords = packet.getRecords(['AN', 'AR'], DNS_RECORD_TYPES.A);
+
+ srvRecords.forEach((record) => {
+ let data = record.data || {};
+
+ services[record.name] = {
+ host: data.target,
+ port: data.port,
+ ttl: record.ttl
+ };
+ });
+
+ txtRecords.forEach((record) => {
+ if (!services[record.name]) {
+ return;
+ }
+
+ services[record.name].attributes = record.data;
+ });
+
+ aRecords.forEach((record) => {
+ if (IsIpv4Address(record.data)) {
+ hosts[record.name] = record.data;
+ }
+ });
+
+ ptrRecords.forEach((record) => {
+ let name = record.data;
+ if (!services[name]) {
+ return;
+ }
+
+ let {host, port} = services[name];
+ if (!host || !port) {
+ return;
+ }
+
+ let { serviceName, serviceType, domainName } = _parseServiceDomainName(name);
+ if (!serviceName || !serviceType || !domainName) {
+ return;
+ }
+
+ let address = hosts[host];
+ if (!address) {
+ return;
+ }
+
+ let ttl = services[name].ttl || 0;
+ let serviceInfo = {
+ serviceName: serviceName,
+ serviceType: serviceType,
+ host: host,
+ address: address,
+ port: port,
+ domainName: domainName,
+ attributes: services[name].attributes || {}
+ };
+
+ this._onServiceFound(serviceInfo, ttl);
+ });
+ }
+
+ _onServiceFound(serviceInfo, ttl = 0) {
+ let expireTime = Date.now() + (ttl * 1000);
+ let key = serviceInfo.serviceName + '.' +
+ serviceInfo.serviceType + '.' +
+ serviceInfo.domainName + ' @' +
+ serviceInfo.address + ':' +
+ serviceInfo.port;
+
+ // If this service was already discovered, just update
+ // its expiration time and don't re-emit it.
+ if (this._discovered.has(key)) {
+ this._discovered.get(key).expireTime = expireTime;
+ return;
+ }
+
+ this._discovered.set(key, {
+ serviceInfo: serviceInfo,
+ expireTime: expireTime
+ });
+
+ let listeners = this._listeners.get(serviceInfo.serviceType) || [];
+ listeners.forEach((listener) => {
+ listener.onServiceFound(serviceInfo);
+ });
+
+ DEBUG && debug('_onServiceFound()' + serviceInfo.serviceName);
+ }
+
+ /**
+ * Gets a non-exclusive socket on 0.0.0.0:{random} to send
+ * multicast queries on all interfaces. This socket does
+ * not need to join a multicast group since it is still
+ * able to *send* multicast queries, but it does not need
+ * to *listen* for multicast queries/announcements since
+ * the `_broadcastReceiverSocket` is already handling them.
+ */
+ _getQuerySocket() {
+ return new Promise((resolve, reject) => {
+ if (!this._querySocket) {
+ this._querySocket = _openSocket('0.0.0.0', 0, {
+ onPacketReceived: this._onPacketReceived.bind(this),
+ onStopListening: this._onStopListening.bind(this)
+ });
+ }
+ resolve(this._querySocket);
+ });
+ }
+
+ /**
+ * Gets a non-exclusive socket on 0.0.0.0:5353 to listen
+ * for multicast queries/announcements on all interfaces.
+ * Since this socket needs to listen for multicast queries
+ * and announcements, this socket joins the multicast
+ * group on *all* interfaces (0.0.0.0).
+ */
+ _getBroadcastReceiverSocket() {
+ return new Promise((resolve, reject) => {
+ if (!this._broadcastReceiverSocket) {
+ this._broadcastReceiverSocket = _openSocket('0.0.0.0', MDNS_PORT, {
+ onPacketReceived: this._onPacketReceived.bind(this),
+ onStopListening: this._onStopListening.bind(this)
+ }, /* multicastInterface = */ '0.0.0.0');
+ }
+ resolve(this._broadcastReceiverSocket);
+ });
+ }
+
+ /**
+ * Gets a non-exclusive socket for each interface on
+ * {iface-ip}:5353 for sending query responses as
+ * well as for listening for unicast queries. These
+ * sockets do not need to join a multicast group
+ * since they are still able to *send* multicast
+ * query responses, but they do not need to *listen*
+ * for multicast queries since the `_querySocket` is
+ * already handling them.
+ */
+ _getSockets() {
+ return new Promise((resolve) => {
+ if (this._sockets.size > 0) {
+ resolve(this._sockets);
+ return;
+ }
+
+ Promise.all([getAddresses(), getHostname()]).then(() => {
+ _addresses.forEach((address) => {
+ let socket = _openSocket(address, MDNS_PORT, null);
+ this._sockets.set(address, socket);
+ });
+
+ resolve(this._sockets);
+ });
+ });
+ }
+
+ _checkCloseSockets() {
+ // Nothing to do if no sockets to close.
+ if (this._sockets.size == 0)
+ return;
+
+ // Don't close sockets if discovery listeners are still present.
+ if (this._listeners.size > 0)
+ return;
+
+ // Don't close sockets if advertised services are present.
+ // Since we need to listen for service queries and respond to them.
+ if (this._services.size > 0)
+ return;
+
+ this._closeSockets();
+ }
+
+ _closeSockets() {
+ this._sockets.forEach(socket => socket.close());
+ this._sockets.clear();
+ }
+
+ _onPacketReceived(socket, message) {
+ let packet = DNSPacket.parse(message.rawData);
+
+ switch (packet.getFlag('QR')) {
+ case DNS_QUERY_RESPONSE_CODES.QUERY:
+ this._handleQueryPacket(packet, message);
+ break;
+ case DNS_QUERY_RESPONSE_CODES.RESPONSE:
+ this._handleResponsePacket(packet, message);
+ break;
+ default:
+ break;
+ }
+ }
+
+ _onStopListening(socket, status) {
+ DEBUG && debug('_onStopListening() ' + status);
+ }
+
+ _addServiceListener(serviceType, listener) {
+ let listeners = this._listeners.get(serviceType);
+ if (!listeners) {
+ listeners = [];
+ this._listeners.set(serviceType, listeners);
+ }
+
+ if (!listeners.find(l => l === listener)) {
+ listeners.push(listener);
+ }
+ }
+
+ _removeServiceListener(serviceType, listener) {
+ let listeners = this._listeners.get(serviceType);
+ if (!listeners) {
+ return;
+ }
+
+ let index = listeners.findIndex(l => l === listener);
+ if (index >= 0) {
+ listeners.splice(index, 1);
+ }
+
+ if (listeners.length === 0) {
+ this._listeners.delete(serviceType);
+ }
+ }
+}
+
+let _addresses;
+
+/**
+ * @private
+ */
+function getAddresses() {
+ return new Promise((resolve, reject) => {
+ if (_addresses) {
+ resolve(_addresses);
+ return;
+ }
+
+ networkInfoService.listNetworkAddresses({
+ onListedNetworkAddresses(aAddressArray) {
+ _addresses = aAddressArray.filter((address) => {
+ return address.indexOf('%p2p') === -1 && // No WiFi Direct interfaces
+ address.indexOf(':') === -1 && // XXX: No IPv6 for now
+ address != "127.0.0.1" // No ipv4 loopback addresses.
+ });
+
+ DEBUG && debug('getAddresses(): ' + _addresses);
+ resolve(_addresses);
+ },
+
+ onListNetworkAddressesFailed() {
+ DEBUG && debug('getAddresses() FAILED!');
+ resolve([]);
+ }
+ });
+ });
+}
+
+let _hostname;
+
+/**
+ * @private
+ */
+function getHostname() {
+ return new Promise((resolve) => {
+ if (_hostname) {
+ resolve(_hostname);
+ return;
+ }
+
+ networkInfoService.getHostname({
+ onGotHostname(aHostname) {
+ _hostname = aHostname.replace(/\s/g, '-') + '.local';
+
+ DEBUG && debug('getHostname(): ' + _hostname);
+ resolve(_hostname);
+ },
+
+ onGetHostnameFailed() {
+ DEBUG && debug('getHostname() FAILED');
+ resolve('localhost');
+ }
+ });
+ });
+}
+
+/**
+ * Parse fully qualified domain name to service name, instance name,
+ * and domain name. See https://tools.ietf.org/html/rfc6763#section-7.
+ *
+ * Example: 'foo-bar-service._http._tcp.local' -> {
+ * serviceName: 'foo-bar-service',
+ * serviceType: '_http._tcp',
+ * domainName: 'local'
+ * }
+ *
+ * @private
+ */
+function _parseServiceDomainName(serviceDomainName) {
+ let parts = serviceDomainName.split('.');
+ let index = Math.max(parts.lastIndexOf('_tcp'), parts.lastIndexOf('_udp'));
+
+ return {
+ serviceName: parts.splice(0, index - 1).join('.'),
+ serviceType: parts.splice(0, 2).join('.'),
+ domainName: parts.join('.')
+ };
+}
+
+/**
+ * @private
+ */
+function _propertyBagToObject(propBag) {
+ let result = {};
+ if (propBag.QueryInterface) {
+ propBag.QueryInterface(Ci.nsIPropertyBag2);
+ let propEnum = propBag.enumerator;
+ while (propEnum.hasMoreElements()) {
+ let prop = propEnum.getNext().QueryInterface(Ci.nsIProperty);
+ result[prop.name] = prop.value.toString();
+ }
+ } else {
+ for (let name in propBag) {
+ result[name] = propBag[name].toString();
+ }
+ }
+ return result;
+}
+
+/**
+ * @private
+ */
+function _openSocket(addr, port, handler, multicastInterface) {
+ let socket = Cc['@mozilla.org/network/udp-socket;1'].createInstance(Ci.nsIUDPSocket);
+ socket.init2(addr, port, Services.scriptSecurityManager.getSystemPrincipal(), true);
+
+ if (handler) {
+ socket.asyncListen({
+ onPacketReceived: handler.onPacketReceived,
+ onStopListening: handler.onStopListening
+ });
+ }
+
+ if (multicastInterface) {
+ socket.joinMulticast(MDNS_MULTICAST_GROUP, multicastInterface);
+ }
+
+ return socket;
+}
diff --git a/netwerk/dns/mdns/libmdns/moz.build b/netwerk/dns/mdns/libmdns/moz.build
new file mode 100644
index 000000000..d2dca4955
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/moz.build
@@ -0,0 +1,56 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa' or \
+ (CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['ANDROID_VERSION'] >= '16'):
+ UNIFIED_SOURCES += [
+ 'MDNSResponderOperator.cpp',
+ 'MDNSResponderReply.cpp',
+ 'nsDNSServiceDiscovery.cpp',
+ ]
+
+ LOCAL_INCLUDES += [
+ '/netwerk/base',
+ ]
+
+ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
+ LOCAL_INCLUDES += [
+ '%' + '%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
+ 'external/mdnsresponder/mDNSShared',
+ ]
+ ]
+
+else:
+ EXTRA_COMPONENTS += [
+ 'nsDNSServiceDiscovery.js',
+ 'nsDNSServiceDiscovery.manifest',
+ ]
+
+ EXTRA_JS_MODULES += [
+ 'fallback/DataReader.jsm',
+ 'fallback/DataWriter.jsm',
+ 'fallback/DNSPacket.jsm',
+ 'fallback/DNSRecord.jsm',
+ 'fallback/DNSResourceRecord.jsm',
+ 'fallback/DNSTypes.jsm',
+ 'fallback/MulticastDNS.jsm',
+ ]
+
+ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
+ EXTRA_JS_MODULES += [
+ 'MulticastDNSAndroid.jsm',
+ ]
+
+UNIFIED_SOURCES += [
+ 'nsDNSServiceInfo.cpp',
+ 'nsMulticastDNSModule.cpp',
+]
+
+include('/ipc/chromium/chromium-config.mozbuild')
+FINAL_LIBRARY = 'xul'
+
+if CONFIG['GNU_CXX']:
+ CXXFLAGS += ['-Wno-error=shadow']
diff --git a/netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.cpp b/netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.cpp
new file mode 100644
index 000000000..8ffa74b71
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.cpp
@@ -0,0 +1,285 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsDNSServiceDiscovery.h"
+#include "MDNSResponderOperator.h"
+#include "nsICancelable.h"
+#include "nsXULAppAPI.h"
+#include "private/pprio.h"
+
+#ifdef MOZ_WIDGET_GONK
+#include <cutils/properties.h>
+#endif // MOZ_WIDGET_GONK
+
+namespace mozilla {
+namespace net {
+
+namespace {
+
+inline void
+StartService()
+{
+#ifdef MOZ_WIDGET_GONK
+ char value[PROPERTY_VALUE_MAX] = { '\0' };
+ property_get("init.svc.mdnsd", value, "");
+
+ if (strcmp(value, "running") == 0) {
+ return;
+ }
+ property_set("ctl.start", "mdnsd");
+#endif // MOZ_WIDGET_GONK
+}
+
+inline void
+StopService()
+{
+#ifdef MOZ_WIDGET_GONK
+ char value[PROPERTY_VALUE_MAX] = { '\0' };
+ property_get("init.svc.mdnsd", value, "");
+
+ if (strcmp(value, "stopped") == 0) {
+ return;
+ }
+ property_set("ctl.stop", "mdnsd");
+#endif // MOZ_WIDGET_GONK
+}
+
+class ServiceCounter
+{
+public:
+ static bool IsServiceRunning()
+ {
+ return !!sUseCount;
+ }
+
+private:
+ static uint32_t sUseCount;
+
+protected:
+ ServiceCounter()
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+ if (!sUseCount++) {
+ StartService();
+ }
+ }
+
+ virtual ~ServiceCounter()
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+ if (!--sUseCount) {
+ StopService();
+ }
+ }
+};
+
+uint32_t ServiceCounter::sUseCount = 0;
+
+class DiscoveryRequest final : public nsICancelable
+ , private ServiceCounter
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICANCELABLE
+
+ explicit DiscoveryRequest(nsDNSServiceDiscovery* aService,
+ nsIDNSServiceDiscoveryListener* aListener);
+
+private:
+ virtual ~DiscoveryRequest() { Cancel(NS_OK); }
+
+ RefPtr<nsDNSServiceDiscovery> mService;
+ nsIDNSServiceDiscoveryListener* mListener;
+};
+
+NS_IMPL_ISUPPORTS(DiscoveryRequest, nsICancelable)
+
+DiscoveryRequest::DiscoveryRequest(nsDNSServiceDiscovery* aService,
+ nsIDNSServiceDiscoveryListener* aListener)
+ : mService(aService)
+ , mListener(aListener)
+{
+}
+
+NS_IMETHODIMP
+DiscoveryRequest::Cancel(nsresult aReason)
+{
+ if (mService) {
+ mService->StopDiscovery(mListener);
+ }
+
+ mService = nullptr;
+ return NS_OK;
+}
+
+class RegisterRequest final : public nsICancelable
+ , private ServiceCounter
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSICANCELABLE
+
+ explicit RegisterRequest(nsDNSServiceDiscovery* aService,
+ nsIDNSRegistrationListener* aListener);
+
+private:
+ virtual ~RegisterRequest() { Cancel(NS_OK); }
+
+ RefPtr<nsDNSServiceDiscovery> mService;
+ nsIDNSRegistrationListener* mListener;
+};
+
+NS_IMPL_ISUPPORTS(RegisterRequest, nsICancelable)
+
+RegisterRequest::RegisterRequest(nsDNSServiceDiscovery* aService,
+ nsIDNSRegistrationListener* aListener)
+ : mService(aService)
+ , mListener(aListener)
+{
+}
+
+NS_IMETHODIMP
+RegisterRequest::Cancel(nsresult aReason)
+{
+ if (mService) {
+ mService->UnregisterService(mListener);
+ }
+
+ mService = nullptr;
+ return NS_OK;
+}
+
+} // namespace anonymous
+
+NS_IMPL_ISUPPORTS(nsDNSServiceDiscovery, nsIDNSServiceDiscovery)
+
+nsDNSServiceDiscovery::~nsDNSServiceDiscovery()
+{
+#ifdef MOZ_WIDGET_GONK
+ StopService();
+#endif
+}
+
+nsresult
+nsDNSServiceDiscovery::Init()
+{
+ if (!XRE_IsParentProcess()) {
+ MOZ_ASSERT(false, "nsDNSServiceDiscovery can only be used in parent process");
+ return NS_ERROR_FAILURE;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSServiceDiscovery::StartDiscovery(const nsACString& aServiceType,
+ nsIDNSServiceDiscoveryListener* aListener,
+ nsICancelable** aRetVal)
+{
+ MOZ_ASSERT(aRetVal);
+
+ nsresult rv;
+ if (NS_WARN_IF(NS_FAILED(rv = StopDiscovery(aListener)))) {
+ return rv;
+ }
+
+ nsCOMPtr<nsICancelable> req = new DiscoveryRequest(this, aListener);
+ RefPtr<BrowseOperator> browserOp = new BrowseOperator(aServiceType,
+ aListener);
+ if (NS_WARN_IF(NS_FAILED(rv = browserOp->Start()))) {
+ return rv;
+ }
+
+ mDiscoveryMap.Put(aListener, browserOp);
+
+ req.forget(aRetVal);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSServiceDiscovery::StopDiscovery(nsIDNSServiceDiscoveryListener* aListener)
+{
+ nsresult rv;
+
+ RefPtr<BrowseOperator> browserOp;
+ if (!mDiscoveryMap.Get(aListener, getter_AddRefs(browserOp))) {
+ return NS_OK;
+ }
+
+ browserOp->Cancel(); // cancel non-started operation
+ if (NS_WARN_IF(NS_FAILED(rv = browserOp->Stop()))) {
+ return rv;
+ }
+
+ mDiscoveryMap.Remove(aListener);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSServiceDiscovery::RegisterService(nsIDNSServiceInfo* aServiceInfo,
+ nsIDNSRegistrationListener* aListener,
+ nsICancelable** aRetVal)
+{
+ MOZ_ASSERT(aRetVal);
+
+ nsresult rv;
+ if (NS_WARN_IF(NS_FAILED(rv = UnregisterService(aListener)))) {
+ return rv;
+ }
+
+ nsCOMPtr<nsICancelable> req = new RegisterRequest(this, aListener);
+ RefPtr<RegisterOperator> registerOp = new RegisterOperator(aServiceInfo,
+ aListener);
+ if (NS_WARN_IF(NS_FAILED(rv = registerOp->Start()))) {
+ return rv;
+ }
+
+ mRegisterMap.Put(aListener, registerOp);
+
+ req.forget(aRetVal);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSServiceDiscovery::UnregisterService(nsIDNSRegistrationListener* aListener)
+{
+ nsresult rv;
+
+ RefPtr<RegisterOperator> registerOp;
+ if (!mRegisterMap.Get(aListener, getter_AddRefs(registerOp))) {
+ return NS_OK;
+ }
+
+ registerOp->Cancel(); // cancel non-started operation
+ if (NS_WARN_IF(NS_FAILED(rv = registerOp->Stop()))) {
+ return rv;
+ }
+
+ mRegisterMap.Remove(aListener);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSServiceDiscovery::ResolveService(nsIDNSServiceInfo* aServiceInfo,
+ nsIDNSServiceResolveListener* aListener)
+{
+ if (!ServiceCounter::IsServiceRunning()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsresult rv;
+
+ RefPtr<ResolveOperator> resolveOp = new ResolveOperator(aServiceInfo,
+ aListener);
+ if (NS_WARN_IF(NS_FAILED(rv = resolveOp->Start()))) {
+ return rv;
+ }
+
+ return NS_OK;
+}
+
+} // namespace net
+} // namespace mozilla
diff --git a/netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.h b/netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.h
new file mode 100644
index 000000000..9bf2c798a
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceDiscovery_h
+#define mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceDiscovery_h
+
+#include "nsIDNSServiceDiscovery.h"
+#include "nsCOMPtr.h"
+#include "mozilla/RefPtr.h"
+#include "nsRefPtrHashtable.h"
+
+namespace mozilla {
+namespace net {
+
+class BrowseOperator;
+class RegisterOperator;
+
+class nsDNSServiceDiscovery final : public nsIDNSServiceDiscovery
+{
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIDNSSERVICEDISCOVERY
+
+ explicit nsDNSServiceDiscovery() = default;
+
+ /*
+ ** The mDNS service is started on demand. If no one uses, mDNS service will not
+ ** start. Therefore, all operations before service started will fail
+ ** and get error code |kDNSServiceErr_ServiceNotRunning| defined in dns_sd.h.
+ **/
+ nsresult Init();
+
+ nsresult StopDiscovery(nsIDNSServiceDiscoveryListener* aListener);
+ nsresult UnregisterService(nsIDNSRegistrationListener* aListener);
+
+private:
+ virtual ~nsDNSServiceDiscovery();
+
+ nsRefPtrHashtable<nsISupportsHashKey, BrowseOperator> mDiscoveryMap;
+ nsRefPtrHashtable<nsISupportsHashKey, RegisterOperator> mRegisterMap;
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif // mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceDiscovery_h
diff --git a/netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.js b/netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.js
new file mode 100644
index 000000000..b94f67297
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.js
@@ -0,0 +1,201 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/ExtensionUtils.jsm");
+Cu.import('resource://gre/modules/Services.jsm');
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+let { PlatformInfo } = ExtensionUtils;
+
+if (PlatformInfo.os == "android" && !Services.prefs.getBoolPref("network.mdns.use_js_fallback")) {
+ Cu.import("resource://gre/modules/MulticastDNSAndroid.jsm");
+} else {
+ Cu.import("resource://gre/modules/MulticastDNS.jsm");
+}
+
+const DNSSERVICEDISCOVERY_CID = Components.ID("{f9346d98-f27a-4e89-b744-493843416480}");
+const DNSSERVICEDISCOVERY_CONTRACT_ID = "@mozilla.org/toolkit/components/mdnsresponder/dns-sd;1";
+const DNSSERVICEINFO_CONTRACT_ID = "@mozilla.org/toolkit/components/mdnsresponder/dns-info;1";
+
+function log(aMsg) {
+ dump("-*- nsDNSServiceDiscovery.js : " + aMsg + "\n");
+}
+
+function generateUuid() {
+ var uuidGenerator = Components.classes["@mozilla.org/uuid-generator;1"].
+ getService(Ci.nsIUUIDGenerator);
+ return uuidGenerator.generateUUID().toString();
+}
+
+// Helper class to transform return objects to correct type.
+function ListenerWrapper(aListener, aMdns) {
+ this.listener = aListener;
+ this.mdns = aMdns;
+
+ this.discoveryStarting = false;
+ this.stopDiscovery = false;
+
+ this.registrationStarting = false;
+ this.stopRegistration = false;
+
+ this.uuid = generateUuid();
+}
+
+ListenerWrapper.prototype = {
+ // Helper function for transforming an Object into nsIDNSServiceInfo.
+ makeServiceInfo: function (aServiceInfo) {
+ let serviceInfo = Cc[DNSSERVICEINFO_CONTRACT_ID].createInstance(Ci.nsIDNSServiceInfo);
+
+ for (let name of ['host', 'address', 'port', 'serviceName', 'serviceType']) {
+ try {
+ serviceInfo[name] = aServiceInfo[name];
+ } catch (e) {
+ // ignore exceptions
+ }
+ }
+
+ let attributes;
+ try {
+ attributes = _toPropertyBag2(aServiceInfo.attributes);
+ } catch (err) {
+ // Ignore unset attributes in object.
+ log("Caught unset attributes error: " + err + " - " + err.stack);
+ attributes = Cc['@mozilla.org/hash-property-bag;1']
+ .createInstance(Ci.nsIWritablePropertyBag2);
+ }
+ serviceInfo.attributes = attributes;
+
+ return serviceInfo;
+ },
+
+ /* transparent types */
+ onDiscoveryStarted: function(aServiceType) {
+ this.discoveryStarting = false;
+ this.listener.onDiscoveryStarted(aServiceType);
+
+ if (this.stopDiscovery) {
+ this.mdns.stopDiscovery(aServiceType, this);
+ }
+ },
+ onDiscoveryStopped: function(aServiceType) {
+ this.listener.onDiscoveryStopped(aServiceType);
+ },
+ onStartDiscoveryFailed: function(aServiceType, aErrorCode) {
+ log('onStartDiscoveryFailed: ' + aServiceType + ' (' + aErrorCode + ')');
+ this.discoveryStarting = false;
+ this.stopDiscovery = true;
+ this.listener.onStartDiscoveryFailed(aServiceType, aErrorCode);
+ },
+ onStopDiscoveryFailed: function(aServiceType, aErrorCode) {
+ log('onStopDiscoveryFailed: ' + aServiceType + ' (' + aErrorCode + ')');
+ this.listener.onStopDiscoveryFailed(aServiceType, aErrorCode);
+ },
+
+ /* transform types */
+ onServiceFound: function(aServiceInfo) {
+ this.listener.onServiceFound(this.makeServiceInfo(aServiceInfo));
+ },
+ onServiceLost: function(aServiceInfo) {
+ this.listener.onServiceLost(this.makeServiceInfo(aServiceInfo));
+ },
+ onServiceRegistered: function(aServiceInfo) {
+ this.registrationStarting = false;
+ this.listener.onServiceRegistered(this.makeServiceInfo(aServiceInfo));
+
+ if (this.stopRegistration) {
+ this.mdns.unregisterService(aServiceInfo, this);
+ }
+ },
+ onServiceUnregistered: function(aServiceInfo) {
+ this.listener.onServiceUnregistered(this.makeServiceInfo(aServiceInfo));
+ },
+ onServiceResolved: function(aServiceInfo) {
+ this.listener.onServiceResolved(this.makeServiceInfo(aServiceInfo));
+ },
+
+ onRegistrationFailed: function(aServiceInfo, aErrorCode) {
+ log('onRegistrationFailed: (' + aErrorCode + ')');
+ this.registrationStarting = false;
+ this.stopRegistration = true;
+ this.listener.onRegistrationFailed(this.makeServiceInfo(aServiceInfo), aErrorCode);
+ },
+ onUnregistrationFailed: function(aServiceInfo, aErrorCode) {
+ log('onUnregistrationFailed: (' + aErrorCode + ')');
+ this.listener.onUnregistrationFailed(this.makeServiceInfo(aServiceInfo), aErrorCode);
+ },
+ onResolveFailed: function(aServiceInfo, aErrorCode) {
+ log('onResolveFailed: (' + aErrorCode + ')');
+ this.listener.onResolveFailed(this.makeServiceInfo(aServiceInfo), aErrorCode);
+ }
+};
+
+function nsDNSServiceDiscovery() {
+ log("nsDNSServiceDiscovery");
+ this.mdns = new MulticastDNS();
+}
+
+nsDNSServiceDiscovery.prototype = {
+ classID: DNSSERVICEDISCOVERY_CID,
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIDNSServiceDiscovery]),
+
+ startDiscovery: function(aServiceType, aListener) {
+ log("startDiscovery");
+ let listener = new ListenerWrapper(aListener, this.mdns);
+ listener.discoveryStarting = true;
+ this.mdns.startDiscovery(aServiceType, listener);
+
+ return {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsICancelable]),
+ cancel: (function() {
+ if (this.discoveryStarting || this.stopDiscovery) {
+ this.stopDiscovery = true;
+ return;
+ }
+ this.mdns.stopDiscovery(aServiceType, listener);
+ }).bind(listener)
+ };
+ },
+
+ registerService: function(aServiceInfo, aListener) {
+ log("registerService");
+ let listener = new ListenerWrapper(aListener, this.mdns);
+ listener.registrationStarting = true;
+ this.mdns.registerService(aServiceInfo, listener);
+
+ return {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsICancelable]),
+ cancel: (function() {
+ if (this.registrationStarting || this.stopRegistration) {
+ this.stopRegistration = true;
+ return;
+ }
+ this.mdns.unregisterService(aServiceInfo, listener);
+ }).bind(listener)
+ };
+ },
+
+ resolveService: function(aServiceInfo, aListener) {
+ log("resolveService");
+ this.mdns.resolveService(aServiceInfo, new ListenerWrapper(aListener));
+ }
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([nsDNSServiceDiscovery]);
+
+function _toPropertyBag2(obj)
+{
+ if (obj.QueryInterface) {
+ return obj.QueryInterface(Ci.nsIPropertyBag2);
+ }
+
+ let result = Cc['@mozilla.org/hash-property-bag;1']
+ .createInstance(Ci.nsIWritablePropertyBag2);
+ for (let name in obj) {
+ result.setPropertyAsAString(name, obj[name]);
+ }
+ return result;
+}
diff --git a/netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.manifest b/netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.manifest
new file mode 100644
index 000000000..c17e719f2
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.manifest
@@ -0,0 +1,3 @@
+# nsDNSServiceDiscovery.js
+component {f9346d98-f27a-4e89-b744-493843416480} nsDNSServiceDiscovery.js
+contract @mozilla.org/toolkit/components/mdnsresponder/dns-sd;1 {f9346d98-f27a-4e89-b744-493843416480}
diff --git a/netwerk/dns/mdns/libmdns/nsDNSServiceInfo.cpp b/netwerk/dns/mdns/libmdns/nsDNSServiceInfo.cpp
new file mode 100644
index 000000000..7c67b49ac
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/nsDNSServiceInfo.cpp
@@ -0,0 +1,209 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsDNSServiceInfo.h"
+#include "nsHashPropertyBag.h"
+#include "nsIProperty.h"
+#include "nsISimpleEnumerator.h"
+#include "nsISupportsImpl.h"
+#include "mozilla/Unused.h"
+
+namespace mozilla {
+namespace net {
+
+NS_IMPL_ISUPPORTS(nsDNSServiceInfo, nsIDNSServiceInfo)
+
+nsDNSServiceInfo::nsDNSServiceInfo(nsIDNSServiceInfo* aServiceInfo)
+{
+ if (NS_WARN_IF(!aServiceInfo)) {
+ return;
+ }
+
+ nsAutoCString str;
+ uint16_t value;
+
+ if (NS_SUCCEEDED(aServiceInfo->GetHost(str))) {
+ Unused << NS_WARN_IF(NS_FAILED(SetHost(str)));
+ }
+ if (NS_SUCCEEDED(aServiceInfo->GetAddress(str))) {
+ Unused << NS_WARN_IF(NS_FAILED(SetAddress(str)));
+ }
+ if (NS_SUCCEEDED(aServiceInfo->GetPort(&value))) {
+ Unused << NS_WARN_IF(NS_FAILED(SetPort(value)));
+ }
+ if (NS_SUCCEEDED(aServiceInfo->GetServiceName(str))) {
+ Unused << NS_WARN_IF(NS_FAILED(SetServiceName(str)));
+ }
+ if (NS_SUCCEEDED(aServiceInfo->GetServiceType(str))) {
+ Unused << NS_WARN_IF(NS_FAILED(SetServiceType(str)));
+ }
+ if (NS_SUCCEEDED(aServiceInfo->GetDomainName(str))) {
+ Unused << NS_WARN_IF(NS_FAILED(SetDomainName(str)));
+ }
+
+ nsCOMPtr<nsIPropertyBag2> attributes; // deep copy
+ if (NS_SUCCEEDED(aServiceInfo->GetAttributes(getter_AddRefs(attributes)))) {
+ nsCOMPtr<nsISimpleEnumerator> enumerator;
+ if (NS_WARN_IF(NS_FAILED(attributes->GetEnumerator(getter_AddRefs(enumerator))))) {
+ return;
+ }
+
+ nsCOMPtr<nsIWritablePropertyBag2> newAttributes = new nsHashPropertyBag();
+
+ bool hasMoreElements;
+ while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreElements)) &&
+ hasMoreElements) {
+ nsCOMPtr<nsISupports> element;
+ Unused <<
+ NS_WARN_IF(NS_FAILED(enumerator->GetNext(getter_AddRefs(element))));
+ nsCOMPtr<nsIProperty> property = do_QueryInterface(element);
+ MOZ_ASSERT(property);
+
+ nsAutoString name;
+ nsCOMPtr<nsIVariant> value;
+ Unused << NS_WARN_IF(NS_FAILED(property->GetName(name)));
+ Unused << NS_WARN_IF(NS_FAILED(property->GetValue(getter_AddRefs(value))));
+ nsAutoCString valueStr;
+ Unused << NS_WARN_IF(NS_FAILED(value->GetAsACString(valueStr)));
+
+ Unused << NS_WARN_IF(NS_FAILED(newAttributes->SetPropertyAsACString(name, valueStr)));
+ }
+
+ Unused << NS_WARN_IF(NS_FAILED(SetAttributes(newAttributes)));
+ }
+}
+
+NS_IMETHODIMP
+nsDNSServiceInfo::GetHost(nsACString& aHost)
+{
+ if (!mIsHostSet) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ aHost = mHost;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSServiceInfo::SetHost(const nsACString& aHost)
+{
+ mHost = aHost;
+ mIsHostSet = true;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSServiceInfo::GetAddress(nsACString& aAddress)
+{
+ if (!mIsAddressSet) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ aAddress = mAddress;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSServiceInfo::SetAddress(const nsACString& aAddress)
+{
+ mAddress = aAddress;
+ mIsAddressSet = true;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSServiceInfo::GetPort(uint16_t* aPort)
+{
+ if (NS_WARN_IF(!aPort)) {
+ return NS_ERROR_INVALID_ARG;
+ }
+ if (!mIsPortSet) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ *aPort = mPort;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSServiceInfo::SetPort(uint16_t aPort)
+{
+ mPort = aPort;
+ mIsPortSet = true;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSServiceInfo::GetServiceName(nsACString& aServiceName)
+{
+ if (!mIsServiceNameSet) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ aServiceName = mServiceName;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSServiceInfo::SetServiceName(const nsACString& aServiceName)
+{
+ mServiceName = aServiceName;
+ mIsServiceNameSet = true;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSServiceInfo::GetServiceType(nsACString& aServiceType)
+{
+ if (!mIsServiceTypeSet) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ aServiceType = mServiceType;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSServiceInfo::SetServiceType(const nsACString& aServiceType)
+{
+ mServiceType = aServiceType;
+ mIsServiceTypeSet = true;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSServiceInfo::GetDomainName(nsACString& aDomainName)
+{
+ if (!mIsDomainNameSet) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ aDomainName = mDomainName;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSServiceInfo::SetDomainName(const nsACString& aDomainName)
+{
+ mDomainName = aDomainName;
+ mIsDomainNameSet = true;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSServiceInfo::GetAttributes(nsIPropertyBag2** aAttributes)
+{
+ if (!mIsAttributesSet) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ nsCOMPtr<nsIPropertyBag2> attributes(mAttributes);
+ attributes.forget(aAttributes);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSServiceInfo::SetAttributes(nsIPropertyBag2* aAttributes)
+{
+ mAttributes = aAttributes;
+ mIsAttributesSet = aAttributes ? true : false;
+ return NS_OK;
+}
+
+} // namespace net
+} // namespace mozilla
diff --git a/netwerk/dns/mdns/libmdns/nsDNSServiceInfo.h b/netwerk/dns/mdns/libmdns/nsDNSServiceInfo.h
new file mode 100644
index 000000000..cca9c5d01
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/nsDNSServiceInfo.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceInfo_h
+#define mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceInfo_h
+
+#include "nsCOMPtr.h"
+#include "nsIDNSServiceDiscovery.h"
+#include "nsIPropertyBag2.h"
+#include "nsString.h"
+
+namespace mozilla {
+namespace net {
+
+class nsDNSServiceInfo final : public nsIDNSServiceInfo
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIDNSSERVICEINFO
+
+ explicit nsDNSServiceInfo() = default;
+ explicit nsDNSServiceInfo(nsIDNSServiceInfo* aServiceInfo);
+
+private:
+ virtual ~nsDNSServiceInfo() = default;
+
+private:
+ nsCString mHost;
+ nsCString mAddress;
+ uint16_t mPort = 0;
+ nsCString mServiceName;
+ nsCString mServiceType;
+ nsCString mDomainName;
+ nsCOMPtr<nsIPropertyBag2> mAttributes;
+
+ bool mIsHostSet = false;
+ bool mIsAddressSet = false;
+ bool mIsPortSet = false;
+ bool mIsServiceNameSet = false;
+ bool mIsServiceTypeSet = false;
+ bool mIsDomainNameSet = false;
+ bool mIsAttributesSet = false;
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif // mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceInfo_h
diff --git a/netwerk/dns/mdns/libmdns/nsMulticastDNSModule.cpp b/netwerk/dns/mdns/libmdns/nsMulticastDNSModule.cpp
new file mode 100644
index 000000000..22bad3bc7
--- /dev/null
+++ b/netwerk/dns/mdns/libmdns/nsMulticastDNSModule.cpp
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#if defined(MOZ_WIDGET_COCOA) || (defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 16)
+#define ENABLE_DNS_SERVICE_DISCOVERY
+#endif
+
+#include "mozilla/ModuleUtils.h"
+
+#ifdef ENABLE_DNS_SERVICE_DISCOVERY
+#include "nsDNSServiceDiscovery.h"
+#endif
+
+#include "nsDNSServiceInfo.h"
+
+#ifdef ENABLE_DNS_SERVICE_DISCOVERY
+using mozilla::net::nsDNSServiceDiscovery;
+#define DNSSERVICEDISCOVERY_CID \
+ {0x8df43d23, 0xd3f9, 0x4dd5, \
+ { 0xb9, 0x65, 0xde, 0x2c, 0xa3, 0xf6, 0xa4, 0x2c }}
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDNSServiceDiscovery, Init)
+NS_DEFINE_NAMED_CID(DNSSERVICEDISCOVERY_CID);
+#endif // ENABLE_DNS_SERVICE_DISCOVERY
+
+using mozilla::net::nsDNSServiceInfo;
+#define DNSSERVICEINFO_CID \
+ {0x14a50f2b, 0x7ff6, 0x48a5, \
+ { 0x88, 0xe3, 0x61, 0x5f, 0xd1, 0x11, 0xf5, 0xd3 }}
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsDNSServiceInfo)
+NS_DEFINE_NAMED_CID(DNSSERVICEINFO_CID);
+
+static const mozilla::Module::CIDEntry knsDNSServiceDiscoveryCIDs[] = {
+#ifdef ENABLE_DNS_SERVICE_DISCOVERY
+ { &kDNSSERVICEDISCOVERY_CID, false, nullptr, nsDNSServiceDiscoveryConstructor },
+#endif
+ { &kDNSSERVICEINFO_CID, false, nullptr, nsDNSServiceInfoConstructor },
+ { nullptr }
+};
+
+static const mozilla::Module::ContractIDEntry knsDNSServiceDiscoveryContracts[] = {
+#ifdef ENABLE_DNS_SERVICE_DISCOVERY
+ { DNSSERVICEDISCOVERY_CONTRACT_ID, &kDNSSERVICEDISCOVERY_CID },
+#endif
+ { DNSSERVICEINFO_CONTRACT_ID, &kDNSSERVICEINFO_CID },
+ { nullptr }
+};
+
+static const mozilla::Module::CategoryEntry knsDNSServiceDiscoveryCategories[] = {
+ { nullptr }
+};
+
+static const mozilla::Module knsDNSServiceDiscoveryModule = {
+ mozilla::Module::kVersion,
+ knsDNSServiceDiscoveryCIDs,
+ knsDNSServiceDiscoveryContracts,
+ knsDNSServiceDiscoveryCategories
+};
+
+NSMODULE_DEFN(nsDNSServiceDiscoveryModule) = &knsDNSServiceDiscoveryModule;
diff --git a/netwerk/dns/mdns/moz.build b/netwerk/dns/mdns/moz.build
new file mode 100644
index 000000000..190bb48e5
--- /dev/null
+++ b/netwerk/dns/mdns/moz.build
@@ -0,0 +1,13 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DIRS += ['libmdns']
+
+XPIDL_SOURCES += [
+ 'nsIDNSServiceDiscovery.idl',
+]
+
+XPIDL_MODULE = 'necko_mdns'
diff --git a/netwerk/dns/mdns/nsIDNSServiceDiscovery.idl b/netwerk/dns/mdns/nsIDNSServiceDiscovery.idl
new file mode 100644
index 000000000..23c678ecc
--- /dev/null
+++ b/netwerk/dns/mdns/nsIDNSServiceDiscovery.idl
@@ -0,0 +1,219 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+interface nsICancelable;
+interface nsIPropertyBag2;
+
+/**
+ * Service information
+ */
+[scriptable, uuid(670ed0f9-2fa5-4544-bf1e-ea58ac179374)]
+interface nsIDNSServiceInfo : nsISupports
+{
+ /**
+ * The host name of the service. (E.g. "Android.local.")
+ * @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
+ */
+ attribute AUTF8String host;
+
+ /**
+ * The IP address of the service.
+ * @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
+ */
+ attribute AUTF8String address;
+
+ /**
+ * The port number of the service. (E.g. 80)
+ * @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
+ */
+ attribute unsigned short port;
+
+ /**
+ * The service name of the service for display. (E.g. "My TV")
+ * @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
+ */
+ attribute AUTF8String serviceName;
+
+ /**
+ * The type of the service. (E.g. "_http._tcp")
+ * @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
+ */
+ attribute AUTF8String serviceType;
+
+ /**
+ * The domain name of the service. (E.g. "local.")
+ * @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
+ */
+ attribute AUTF8String domainName;
+
+ /**
+ * The attributes of the service.
+ */
+ attribute nsIPropertyBag2 attributes;
+};
+
+/**
+ * The callback interface for service discovery
+ */
+[scriptable, uuid(3025b7f2-97bb-435b-b43d-26731b3f5fc4)]
+interface nsIDNSServiceDiscoveryListener : nsISupports
+{
+ /**
+ * Callback when the discovery begins.
+ * @param aServiceType
+ * the service type of |startDiscovery|.
+ */
+ void onDiscoveryStarted(in AUTF8String aServiceType);
+
+ /**
+ * Callback when the discovery ends.
+ * @param aServiceType
+ * the service type of |startDiscovery|.
+ */
+ void onDiscoveryStopped(in AUTF8String aServiceType);
+
+ /**
+ * Callback when the a service is found.
+ * @param aServiceInfo
+ * the info about the found service, where |serviceName|, |aServiceType|, and |domainName| are set.
+ */
+ void onServiceFound(in nsIDNSServiceInfo aServiceInfo);
+
+ /**
+ * Callback when the a service is lost.
+ * @param aServiceInfo
+ * the info about the lost service, where |serviceName|, |aServiceType|, and |domainName| are set.
+ */
+ void onServiceLost(in nsIDNSServiceInfo aServiceInfo);
+
+ /**
+ * Callback when the discovery cannot start.
+ * @param aServiceType
+ * the service type of |startDiscovery|.
+ * @param aErrorCode
+ * the error code.
+ */
+ void onStartDiscoveryFailed(in AUTF8String aServiceType, in long aErrorCode);
+
+ /**
+ * Callback when the discovery cannot stop.
+ * @param aServiceType
+ * the service type of |startDiscovery|.
+ * @param aErrorCode
+ * the error code.
+ */
+ void onStopDiscoveryFailed(in AUTF8String aServiceType, in long aErrorCode);
+};
+
+/**
+ * The callback interface for service registration
+ */
+[scriptable, uuid(e165e4be-abf4-4963-a66d-ed3ca116e5e4)]
+interface nsIDNSRegistrationListener : nsISupports
+{
+ const long ERROR_SERVICE_NOT_RUNNING = -65563;
+
+ /**
+ * Callback when the service is registered successfully.
+ * @param aServiceInfo
+ * the info about the registered service,
+ * where |serviceName|, |aServiceType|, and |domainName| are set.
+ */
+ void onServiceRegistered(in nsIDNSServiceInfo aServiceInfo);
+
+ /**
+ * Callback when the service is unregistered successfully.
+ * @param aServiceInfo
+ * the info about the unregistered service.
+ */
+ void onServiceUnregistered(in nsIDNSServiceInfo aServiceInfo);
+
+ /**
+ * Callback when the service cannot be registered.
+ * @param aServiceInfo
+ * the info about the service to be registered.
+ * @param aErrorCode
+ * the error code.
+ */
+ void onRegistrationFailed(in nsIDNSServiceInfo aServiceInfo, in long aErrorCode);
+
+ /**
+ * Callback when the service cannot be unregistered.
+ * @param aServiceInfo
+ * the info about the registered service.
+ * @param aErrorCode
+ * the error code.
+ */
+ void onUnregistrationFailed(in nsIDNSServiceInfo aServiceInfo, in long aErrorCode);
+};
+
+/**
+ * The callback interface for service resolve
+ */
+[scriptable, uuid(24ee6408-648e-421d-accf-c6e5adeccf97)]
+interface nsIDNSServiceResolveListener : nsISupports
+{
+ /**
+ * Callback when the service is resolved successfully.
+ * @param aServiceInfo
+ * the info about the resolved service, where |host| and |port| are set.
+ */
+ void onServiceResolved(in nsIDNSServiceInfo aServiceInfo);
+
+ /**
+ * Callback when the service cannot be resolved.
+ * @param aServiceInfo
+ * the info about the service to be resolved.
+ * @param aErrorCode
+ * the error code.
+ */
+ void onResolveFailed(in nsIDNSServiceInfo aServiceInfo, in long aErrorCode);
+};
+
+/**
+ * The interface for DNS service discovery/registration/resolve
+ */
+[scriptable, uuid(6487899b-beb1-455a-ba65-e4fd465066d7)]
+interface nsIDNSServiceDiscovery : nsISupports
+{
+ /**
+ * Browse for instances of a service.
+ * @param aServiceType
+ * the service type to be discovered, E.g. "_http._tcp".
+ * @param aListener
+ * callback interface for discovery notifications.
+ * @return An object that can be used to cancel the service discovery.
+ */
+ nsICancelable startDiscovery(in AUTF8String aServiceType, in nsIDNSServiceDiscoveryListener aListener);
+
+ /**
+ * Register a service that is discovered via |startDiscovery| and |resolveService| calls.
+ * @param aServiceInfo
+ * the service information to be registered.
+ * |port| and |aServiceType| are required attributes.
+ * @param aListener
+ * callback interface for registration notifications.
+ * @return An object that can be used to cancel the service registration.
+ */
+ nsICancelable registerService(in nsIDNSServiceInfo aServiceInfo, in nsIDNSRegistrationListener aListener);
+
+ /**
+ * Resolve a service name discovered via |startDiscovery| to a target host name, port number.
+ * @param aServiceInfo
+ * the service information to be registered.
+ * |serviceName|, |aServiceType|, and |domainName| are required attributes as reported to the |onServiceFound| callback.
+ * @param aListener
+ * callback interface for registration notifications.
+ */
+ void resolveService(in nsIDNSServiceInfo aServiceInfo, in nsIDNSServiceResolveListener aListener);
+};
+
+%{ C++
+#define DNSSERVICEDISCOVERY_CONTRACT_ID \
+ "@mozilla.org/toolkit/components/mdnsresponder/dns-sd;1"
+#define DNSSERVICEINFO_CONTRACT_ID \
+ "@mozilla.org/toolkit/components/mdnsresponder/dns-info;1"
+%}
diff --git a/netwerk/dns/moz.build b/netwerk/dns/moz.build
new file mode 100644
index 000000000..f788d9a33
--- /dev/null
+++ b/netwerk/dns/moz.build
@@ -0,0 +1,78 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DIRS += [
+ 'mdns',
+]
+
+XPIDL_SOURCES += [
+ 'nsIDNSListener.idl',
+ 'nsIDNSRecord.idl',
+ 'nsIDNSService.idl',
+ 'nsIEffectiveTLDService.idl',
+ 'nsIIDNService.idl',
+ 'nsPIDNSService.idl',
+]
+
+XPIDL_MODULE = 'necko_dns'
+
+EXPORTS.mozilla.net += [
+ 'ChildDNSService.h',
+ 'DNS.h',
+ 'DNSListenerProxy.h',
+ 'DNSRequestChild.h',
+ 'DNSRequestParent.h',
+ 'PDNSParams.h',
+]
+
+SOURCES += [
+ 'nsEffectiveTLDService.cpp', # Excluded from UNIFIED_SOURCES due to special build flags.
+ 'nsHostResolver.cpp', # Redefines LOG
+]
+
+UNIFIED_SOURCES += [
+ 'ChildDNSService.cpp',
+ 'DNS.cpp',
+ 'DNSListenerProxy.cpp',
+ 'DNSRequestChild.cpp',
+ 'DNSRequestParent.cpp',
+ 'GetAddrInfo.cpp',
+ 'nsDNSService2.cpp',
+ 'nsIDNService.cpp',
+ 'punycode.c',
+]
+
+IPDL_SOURCES = [
+ 'PDNSRequest.ipdl',
+ 'PDNSRequestParams.ipdlh',
+]
+
+include('/ipc/chromium/chromium-config.mozbuild')
+
+FINAL_LIBRARY = 'xul'
+
+GENERATED_FILES = [
+ 'etld_data.inc',
+]
+etld_data = GENERATED_FILES['etld_data.inc']
+etld_data.script = 'prepare_tlds.py'
+etld_data.inputs = ['effective_tld_names.dat']
+
+# need to include etld_data.inc
+LOCAL_INCLUDES += [
+ '/netwerk/base',
+]
+
+if CONFIG['ENABLE_INTL_API']:
+ DEFINES['IDNA2008'] = True
+ USE_LIBS += ['icu']
+else:
+ UNIFIED_SOURCES += [
+ 'nameprep.c',
+ ]
+
+if CONFIG['GNU_CXX']:
+ CXXFLAGS += ['-Wno-error=shadow']
diff --git a/netwerk/dns/nameprep.c b/netwerk/dns/nameprep.c
new file mode 100644
index 000000000..039797885
--- /dev/null
+++ b/netwerk/dns/nameprep.c
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "nsIDNKitInterface.h"
+
+#define UCS_MAX 0x7fffffff
+#define UNICODE_MAX 0x10ffff
+
+
+/*
+ * Load NAMEPREP compiled tables.
+ */
+#include "nameprepdata.c"
+
+/*
+ * Define mapping/checking functions for each version of the draft.
+ */
+
+#define VERSION id11
+#include "nameprep_template.c"
+#undef VERSION
+
+typedef const char *(*nameprep_mapproc)(uint32_t v);
+typedef int (*nameprep_checkproc)(uint32_t v);
+typedef idn_biditype_t (*nameprep_biditypeproc)(uint32_t v);
+
+static struct idn_nameprep {
+ char *version;
+ nameprep_mapproc map_proc;
+ nameprep_checkproc prohibited_proc;
+ nameprep_checkproc unassigned_proc;
+ nameprep_biditypeproc biditype_proc;
+} nameprep_versions[] = {
+#define MAKE_NAMEPREP_HANDLE(version, id) \
+ { version, \
+ compose_sym2(nameprep_map_, id), \
+ compose_sym2(nameprep_prohibited_, id), \
+ compose_sym2(nameprep_unassigned_, id), \
+ compose_sym2(nameprep_biditype_, id), }
+ MAKE_NAMEPREP_HANDLE("nameprep-11", id11),
+ { NULL, NULL, NULL, NULL, NULL },
+};
+
+static idn_result_t idn_nameprep_check(nameprep_checkproc proc,
+ const uint32_t *str,
+ const uint32_t **found);
+
+idn_result_t
+idn_nameprep_create(const char *version, idn_nameprep_t *handlep) {
+ idn_nameprep_t handle;
+
+ assert(handlep != NULL);
+
+ TRACE(("idn_nameprep_create(version=%-.50s)\n",
+ version == NULL ? "<NULL>" : version));
+
+ if (version == NULL)
+ version = IDN_NAMEPREP_CURRENT;
+
+ /*
+ * Lookup table for the specified version. Since the number of
+ * versions won't be large (I don't want see draft-23 or such :-),
+ * simple linear search is OK.
+ */
+ for (handle = nameprep_versions; handle->version != NULL; handle++) {
+ if (strcmp(handle->version, version) == 0) {
+ *handlep = handle;
+ return (idn_success);
+ }
+ }
+ return (idn_notfound);
+}
+
+void
+idn_nameprep_destroy(idn_nameprep_t handle) {
+ assert(handle != NULL);
+
+ TRACE(("idn_nameprep_destroy()\n"));
+
+ /* Nothing to do. */
+}
+
+idn_result_t
+idn_nameprep_map(idn_nameprep_t handle, const uint32_t *from,
+ uint32_t *to, size_t tolen) {
+ assert(handle != NULL && from != NULL && to != NULL);
+
+ TRACE(("idn_nameprep_map(ctx=%s, from=\"%s\")\n",
+ handle->version, idn__debug_ucs4xstring(from, 50)));
+
+ while (*from != '\0') {
+ uint32_t v = *from;
+ const char *mapped;
+
+ if (v > UCS_MAX) {
+ /* This cannot happen, but just in case.. */
+ return (idn_invalid_codepoint);
+ } else if (v > UNICODE_MAX) {
+ /* No mapping is possible. */
+ mapped = NULL;
+ } else {
+ /* Try mapping. */
+ mapped = (*handle->map_proc)(v);
+ }
+
+ if (mapped == NULL) {
+ /* No mapping. Just copy verbatim. */
+ if (tolen < 1)
+ return (idn_buffer_overflow);
+ *to++ = v;
+ tolen--;
+ } else {
+ const unsigned char *mappeddata;
+ size_t mappedlen;
+
+ mappeddata = (const unsigned char *)mapped + 1;
+ mappedlen = *mapped;
+
+ if (tolen < (mappedlen + 3) / 4)
+ return (idn_buffer_overflow);
+ tolen -= (mappedlen + 3) / 4;
+ while (mappedlen >= 4) {
+ *to = *mappeddata++;
+ *to |= *mappeddata++ << 8;
+ *to |= *mappeddata++ << 16;
+ *to |= *mappeddata++ << 24;
+ mappedlen -= 4;
+ to++;
+ }
+ if (mappedlen > 0) {
+ *to = *mappeddata++;
+ *to |= (mappedlen >= 2) ?
+ *mappeddata++ << 8: 0;
+ *to |= (mappedlen >= 3) ?
+ *mappeddata++ << 16: 0;
+ to++;
+ }
+ }
+ from++;
+ }
+ if (tolen == 0)
+ return (idn_buffer_overflow);
+ *to = '\0';
+ return (idn_success);
+}
+
+idn_result_t
+idn_nameprep_isprohibited(idn_nameprep_t handle, const uint32_t *str,
+ const uint32_t **found) {
+ assert(handle != NULL && str != NULL && found != NULL);
+
+ TRACE(("idn_nameprep_isprohibited(ctx=%s, str=\"%s\")\n",
+ handle->version, idn__debug_ucs4xstring(str, 50)));
+
+ return (idn_nameprep_check(handle->prohibited_proc, str, found));
+}
+
+idn_result_t
+idn_nameprep_isunassigned(idn_nameprep_t handle, const uint32_t *str,
+ const uint32_t **found) {
+ assert(handle != NULL && str != NULL && found != NULL);
+
+ TRACE(("idn_nameprep_isunassigned(handle->version, str=\"%s\")\n",
+ handle->version, idn__debug_ucs4xstring(str, 50)));
+
+ return (idn_nameprep_check(handle->unassigned_proc, str, found));
+}
+
+static idn_result_t
+idn_nameprep_check(nameprep_checkproc proc, const uint32_t *str,
+ const uint32_t **found) {
+ uint32_t v;
+
+ while (*str != '\0') {
+ v = *str;
+
+ if (v > UCS_MAX) {
+ /* This cannot happen, but just in case.. */
+ return (idn_invalid_codepoint);
+ } else if (v > UNICODE_MAX) {
+ /* It is invalid.. */
+ *found = str;
+ return (idn_success);
+ } else if ((*proc)(v)) {
+ *found = str;
+ return (idn_success);
+ }
+ str++;
+ }
+ *found = NULL;
+ return (idn_success);
+}
+
+idn_result_t
+idn_nameprep_isvalidbidi(idn_nameprep_t handle, const uint32_t *str,
+ const uint32_t **found) {
+ uint32_t v;
+ idn_biditype_t first_char;
+ idn_biditype_t last_char;
+ int found_r_al;
+
+ assert(handle != NULL && str != NULL && found != NULL);
+
+ TRACE(("idn_nameprep_isvalidbidi(ctx=%s, str=\"%s\")\n",
+ handle->version, idn__debug_ucs4xstring(str, 50)));
+
+ if (*str == '\0') {
+ *found = NULL;
+ return (idn_success);
+ }
+
+ /*
+ * check first character's type and initialize variables.
+ */
+ found_r_al = 0;
+ if (*str > UCS_MAX) {
+ /* This cannot happen, but just in case.. */
+ return (idn_invalid_codepoint);
+ } else if (*str > UNICODE_MAX) {
+ /* It is invalid.. */
+ *found = str;
+ return (idn_success);
+ }
+ first_char = last_char = (*(handle->biditype_proc))(*str);
+ if (first_char == idn_biditype_r_al) {
+ found_r_al = 1;
+ }
+ str++;
+
+ /*
+ * see whether string is valid or not.
+ */
+ while (*str != '\0') {
+ v = *str;
+
+ if (v > UCS_MAX) {
+ /* This cannot happen, but just in case.. */
+ return (idn_invalid_codepoint);
+ } else if (v > UNICODE_MAX) {
+ /* It is invalid.. */
+ *found = str;
+ return (idn_success);
+ } else {
+ last_char = (*(handle->biditype_proc))(v);
+ if (found_r_al && last_char == idn_biditype_l) {
+ *found = str;
+ return (idn_success);
+ }
+ if (first_char != idn_biditype_r_al && last_char == idn_biditype_r_al) {
+ *found = str;
+ return (idn_success);
+ }
+ if (last_char == idn_biditype_r_al) {
+ found_r_al = 1;
+ }
+ }
+ str++;
+ }
+
+ if (found_r_al) {
+ if (last_char != idn_biditype_r_al) {
+ *found = str - 1;
+ return (idn_success);
+ }
+ }
+
+ *found = NULL;
+ return (idn_success);
+}
+
+idn_result_t
+idn_nameprep_createproc(const char *parameter, void **handlep) {
+ return idn_nameprep_create(parameter, (idn_nameprep_t *)handlep);
+}
+
+void
+idn_nameprep_destroyproc(void *handle) {
+ idn_nameprep_destroy((idn_nameprep_t)handle);
+}
+
+idn_result_t
+idn_nameprep_mapproc(void *handle, const uint32_t *from,
+ uint32_t *to, size_t tolen) {
+ return idn_nameprep_map((idn_nameprep_t)handle, from, to, tolen);
+}
+
+idn_result_t
+idn_nameprep_prohibitproc(void *handle, const uint32_t *str,
+ const uint32_t **found) {
+ return idn_nameprep_isprohibited((idn_nameprep_t)handle, str, found);
+}
+
+idn_result_t
+idn_nameprep_unassignedproc(void *handle, const uint32_t *str,
+ const uint32_t **found) {
+ return idn_nameprep_isunassigned((idn_nameprep_t)handle, str, found);
+}
+
+idn_result_t
+idn_nameprep_bidiproc(void *handle, const uint32_t *str,
+ const uint32_t **found) {
+ return idn_nameprep_isvalidbidi((idn_nameprep_t)handle, str, found);
+}
diff --git a/netwerk/dns/nameprep_template.c b/netwerk/dns/nameprep_template.c
new file mode 100644
index 000000000..7fe36518a
--- /dev/null
+++ b/netwerk/dns/nameprep_template.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2001 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/*
+ * Include this file once for each version of NAMEPREP.
+ * VERSION should be defined to appropriate value before inclusion.
+ */
+
+#ifndef NAMEPREP_TEMPLATE_INIT
+#define NAMEPREP_TEMPLATE_INIT
+
+/* Symbol composition. */
+#define compose_sym2(a, b) compose_sym2X(a, b)
+#define compose_sym2X(a, b) a ## b
+#define compose_sym3(a, b, c) compose_sym3X(a, b, c)
+#define compose_sym3X(a, b, c) a ## b ## c
+
+/* The table is based on "Optimized Two-Stage Table" mentioned in
+ * Unicode 3.0 page 106, extended to handle 21bit data instead of 16 bit.
+ */
+
+/* Index calculation for multi-level index tables. */
+#define IDX0(type, v) IDX_0(v, BITS1(type), BITS2(type))
+#define IDX1(type, v) IDX_1(v, BITS1(type), BITS2(type))
+#define IDX2(type, v) IDX_2(v, BITS1(type), BITS2(type))
+
+#define IDX_0(v, bits1, bits2) ((v) >> ((bits1) + (bits2)))
+#define IDX_1(v, bits1, bits2) (((v) >> (bits2)) & ((1 << (bits1)) - 1))
+#define IDX_2(v, bits1, bits2) ((v) & ((1 << (bits2)) - 1))
+
+#define BITS1(type) type ## _BITS_1
+#define BITS2(type) type ## _BITS_2
+
+#endif /* NAMEPREP_TEMPLATE_INIT */
+
+static const char *
+compose_sym2(nameprep_map_, VERSION) (uint32_t v) {
+ int idx0 = IDX0(MAP, v);
+ int idx1 = IDX1(MAP, v);
+ int idx2 = IDX2(MAP, v);
+ int offset;
+
+#define IMAP compose_sym3(nameprep_, VERSION, _map_imap)
+#define TABLE compose_sym3(nameprep_, VERSION, _map_table)
+#define DATA compose_sym3(nameprep_, VERSION, _map_data)
+ offset = TABLE[IMAP[IMAP[idx0] + idx1]].tbl[idx2];
+ if (offset == 0)
+ return (NULL); /* no mapping */
+ return (const char *)(DATA + offset);
+#undef IMAP
+#undef TABLE
+#undef DATA
+}
+
+static int
+compose_sym2(nameprep_prohibited_, VERSION) (uint32_t v) {
+ int idx0 = IDX0(PROH, v);
+ int idx1 = IDX1(PROH, v);
+ int idx2 = IDX2(PROH, v);
+ const unsigned char *bm;
+
+#define IMAP compose_sym3(nameprep_, VERSION, _prohibited_imap)
+#define BITMAP compose_sym3(nameprep_, VERSION, _prohibited_bitmap)
+ bm = BITMAP[IMAP[IMAP[idx0] + idx1]].bm;
+ return (bm[idx2 / 8] & (1 << (idx2 % 8)));
+#undef IMAP
+#undef BITMAP
+}
+
+static int
+compose_sym2(nameprep_unassigned_, VERSION) (uint32_t v) {
+ int idx0 = IDX0(UNAS, v);
+ int idx1 = IDX1(UNAS, v);
+ int idx2 = IDX2(UNAS, v);
+ const unsigned char *bm;
+
+#define IMAP compose_sym3(nameprep_, VERSION, _unassigned_imap)
+#define BITMAP compose_sym3(nameprep_, VERSION, _unassigned_bitmap)
+ bm = BITMAP[IMAP[IMAP[idx0] + idx1]].bm;
+ return (bm[idx2 / 8] & (1 << (idx2 % 8)));
+#undef IMAP
+#undef BITMAP
+}
+
+static idn_biditype_t
+compose_sym2(nameprep_biditype_, VERSION) (uint32_t v) {
+ int idx0 = IDX0(BIDI, v);
+ int idx1 = IDX1(BIDI, v);
+ int idx2 = IDX2(BIDI, v);
+ int offset;
+
+#define IMAP compose_sym3(nameprep_, VERSION, _bidi_imap)
+#define TABLE compose_sym3(nameprep_, VERSION, _bidi_table)
+#define DATA compose_sym3(nameprep_, VERSION, _bidi_data)
+ offset = TABLE[IMAP[IMAP[idx0] + idx1]].tbl[idx2];
+ return DATA[offset];
+#undef IMAP
+#undef TABLE
+#undef DATA
+}
diff --git a/netwerk/dns/nameprepdata.c b/netwerk/dns/nameprepdata.c
new file mode 100644
index 000000000..cd7e2db0e
--- /dev/null
+++ b/netwerk/dns/nameprepdata.c
@@ -0,0 +1,2588 @@
+/*
+ * Copyright (c) 2001,2002 Japan Network Information Center.
+ * All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+ *
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+ /*
+ * Do not edit this file!
+ * This file is generated from NAMEPREP specification.
+ */
+
+#define MAP_BITS_0 9
+#define MAP_BITS_1 7
+#define MAP_BITS_2 5
+
+#define PROH_BITS_0 7
+#define PROH_BITS_1 7
+#define PROH_BITS_2 7
+
+#define UNAS_BITS_0 7
+#define UNAS_BITS_1 7
+#define UNAS_BITS_2 7
+
+#define BIDI_BITS_0 9
+#define BIDI_BITS_1 7
+#define BIDI_BITS_2 5
+
+
+static const unsigned short nameprep_id11_map_imap[] = {
+ 272, 400, 528, 656, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 912,
+ 1040, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 1168, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 784, 784, 784, 784, 784, 784, 784, 784,
+ 0, 0, 1, 0, 0, 2, 3, 0,
+ 4, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 0, 0, 0, 0, 0, 0,
+ 0, 0, 14, 15, 16, 17, 18, 19,
+ 20, 21, 0, 22, 23, 24, 25, 26,
+ 27, 28, 29, 0, 30, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 31, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 0, 0, 49, 0, 50, 0, 0,
+ 51, 52, 53, 54, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 55, 56, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 57, 58, 59, 60, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 61, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 62, 0, 0, 0, 0, 0, 0, 63,
+ 0, 64, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 65, 66, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 67, 68, 69, 70, 71, 72, 73, 74,
+ 75, 76, 77, 78, 79, 67, 68, 69,
+ 70, 80, 81, 73, 74, 82, 83, 84,
+ 85, 86, 87, 88, 89, 90, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static const struct {
+ unsigned short tbl[32];
+} nameprep_id11_map_table[] = {
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
+ 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42,
+ 44, 46, 48, 50, 52, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 54,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77,
+ 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99,
+ 101, 0, 103, 105, 107, 109, 111, 113, 115, 117,
+ }},
+ {{
+ 123, 0, 126, 0, 129, 0, 132, 0, 135, 0, 138,
+ 0, 141, 0, 144, 0, 147, 0, 150, 0, 153, 0,
+ 156, 0, 159, 0, 162, 0, 165, 0, 168, 0,
+ }},
+ {{
+ 171, 0, 174, 0, 177, 0, 180, 0, 183, 0, 186,
+ 0, 189, 0, 192, 0, 195, 0, 202, 0, 205, 0,
+ 208, 0, 0, 211, 0, 214, 0, 217, 0, 220,
+ }},
+ {{
+ 0, 223, 0, 226, 0, 229, 0, 232, 0, 235, 241,
+ 0, 244, 0, 247, 0, 250, 0, 253, 0, 256, 0,
+ 259, 0, 262, 0, 265, 0, 268, 0, 271, 0,
+ }},
+ {{
+ 274, 0, 277, 0, 280, 0, 283, 0, 286, 0, 289,
+ 0, 292, 0, 295, 0, 298, 0, 301, 0, 304, 0,
+ 307, 0, 310, 312, 0, 315, 0, 318, 0, 38,
+ }},
+ {{
+ 0, 321, 324, 0, 327, 0, 330, 333, 0, 336, 339,
+ 342, 0, 0, 345, 348, 351, 354, 0, 357, 360, 0,
+ 363, 366, 369, 0, 0, 0, 372, 375, 0, 378,
+ }},
+ {{
+ 381, 0, 384, 0, 387, 0, 390, 393, 0, 396, 0,
+ 0, 399, 0, 402, 405, 0, 408, 411, 414, 0, 417,
+ 0, 420, 423, 0, 0, 0, 426, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 429, 429, 0, 432, 432, 0, 435,
+ 435, 0, 438, 0, 441, 0, 444, 0, 447, 0, 450,
+ 0, 453, 0, 456, 0, 459, 0, 0, 462, 0,
+ }},
+ {{
+ 465, 0, 468, 0, 471, 0, 474, 0, 477, 0, 480,
+ 0, 483, 0, 486, 0, 489, 496, 496, 0, 499, 0,
+ 502, 505, 508, 0, 511, 0, 514, 0, 517, 0,
+ }},
+ {{
+ 520, 0, 523, 0, 526, 0, 529, 0, 532, 0, 535,
+ 0, 538, 0, 541, 0, 544, 0, 547, 0, 550, 0,
+ 553, 0, 556, 0, 559, 0, 562, 0, 565, 0,
+ }},
+ {{
+ 568, 0, 571, 0, 574, 0, 577, 0, 580, 0, 583,
+ 0, 586, 0, 589, 0, 592, 0, 595, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 598, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 601, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 608, 0, 611, 614, 617,
+ 0, 620, 0, 623, 626, 629, 640, 643, 646, 649, 652,
+ 655, 658, 661, 598, 664, 667, 54, 670, 673, 676,
+ }},
+ {{
+ 679, 682, 0, 685, 688, 691, 694, 697, 700, 703, 706,
+ 709, 0, 0, 0, 0, 712, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 685, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 643, 661, 691, 623, 709, 694,
+ 679, 0, 723, 0, 726, 0, 729, 0, 732, 0,
+ }},
+ {{
+ 735, 0, 738, 0, 741, 0, 744, 0, 747, 0, 750,
+ 0, 753, 0, 756, 0, 664, 682, 685, 0, 661, 652,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 759, 762, 765, 768, 771, 774, 777, 780, 783, 786, 789,
+ 792, 795, 798, 801, 804, 807, 810, 813, 816, 819, 822,
+ 825, 828, 831, 834, 837, 840, 843, 846, 849, 852,
+ }},
+ {{
+ 855, 858, 861, 864, 867, 870, 873, 876, 879, 882, 885,
+ 888, 891, 894, 897, 900, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 903, 0, 906, 0, 909, 0, 912, 0, 915, 0, 918,
+ 0, 921, 0, 924, 0, 927, 0, 930, 0, 933, 0,
+ 936, 0, 939, 0, 942, 0, 945, 0, 948, 0,
+ }},
+ {{
+ 951, 0, 0, 0, 0, 0, 0, 0, 0, 0, 954,
+ 0, 957, 0, 960, 0, 963, 0, 966, 0, 969, 0,
+ 972, 0, 975, 0, 978, 0, 981, 0, 984, 0,
+ }},
+ {{
+ 987, 0, 990, 0, 993, 0, 996, 0, 999, 0, 1002,
+ 0, 1005, 0, 1008, 0, 1011, 0, 1014, 0, 1017, 0,
+ 1020, 0, 1023, 0, 1026, 0, 1029, 0, 1032, 0,
+ }},
+ {{
+ 0, 1035, 0, 1038, 0, 1041, 0, 1044, 0, 1047, 0,
+ 1050, 0, 1053, 0, 0, 1056, 0, 1059, 0, 1062, 0,
+ 1065, 0, 1068, 0, 1071, 0, 1074, 0, 1077, 0,
+ }},
+ {{
+ 1080, 0, 1083, 0, 1086, 0, 1089, 0, 1092, 0, 1095,
+ 0, 1098, 0, 1101, 0, 1104, 0, 1107, 0, 1110, 0,
+ 0, 0, 1113, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1116, 0, 1119, 0, 1122, 0, 1125, 0, 1128, 0, 1131,
+ 0, 1134, 0, 1137, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1140, 1143, 1146, 1149, 1152,
+ 1155, 1158, 1161, 1164, 1167, 1170, 1173, 1176, 1179, 1182,
+ }},
+ {{
+ 1185, 1188, 1191, 1194, 1197, 1200, 1203, 1206, 1209, 1212, 1215,
+ 1218, 1221, 1224, 1227, 1230, 1233, 1236, 1239, 1242, 1245, 1248,
+ 1251, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 1254, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1261, 0, 1264, 0, 1267, 0, 1270, 0, 1273, 0, 1276,
+ 0, 1279, 0, 1282, 0, 1285, 0, 1288, 0, 1291, 0,
+ 1294, 0, 1297, 0, 1300, 0, 1303, 0, 1306, 0,
+ }},
+ {{
+ 1309, 0, 1312, 0, 1315, 0, 1318, 0, 1321, 0, 1324,
+ 0, 1327, 0, 1330, 0, 1333, 0, 1336, 0, 1339, 0,
+ 1342, 0, 1345, 0, 1348, 0, 1351, 0, 1354, 0,
+ }},
+ {{
+ 1357, 0, 1360, 0, 1363, 0, 1366, 0, 1369, 0, 1372,
+ 0, 1375, 0, 1378, 0, 1381, 0, 1384, 0, 1387, 0,
+ 1390, 0, 1393, 0, 1396, 0, 1399, 0, 1402, 0,
+ }},
+ {{
+ 1405, 0, 1408, 0, 1411, 0, 1414, 0, 1417, 0, 1420,
+ 0, 1423, 0, 1426, 0, 1429, 0, 1432, 0, 1435, 0,
+ 1438, 0, 1441, 0, 1444, 0, 1447, 0, 1450, 0,
+ }},
+ {{
+ 1453, 0, 1456, 0, 1459, 0, 1462, 0, 1465, 0, 1468,
+ 0, 1471, 0, 1474, 0, 1477, 0, 1480, 0, 1483, 0,
+ 1486, 1493, 1500, 1507, 1514, 1405, 0, 0, 0, 0,
+ }},
+ {{
+ 1521, 0, 1524, 0, 1527, 0, 1530, 0, 1533, 0, 1536,
+ 0, 1539, 0, 1542, 0, 1545, 0, 1548, 0, 1551, 0,
+ 1554, 0, 1557, 0, 1560, 0, 1563, 0, 1566, 0,
+ }},
+ {{
+ 1569, 0, 1572, 0, 1575, 0, 1578, 0, 1581, 0, 1584,
+ 0, 1587, 0, 1590, 0, 1593, 0, 1596, 0, 1599, 0,
+ 1602, 0, 1605, 0, 1608, 0, 1611, 0, 1614, 0,
+ }},
+ {{
+ 1617, 0, 1620, 0, 1623, 0, 1626, 0, 1629, 0, 1632,
+ 0, 1635, 0, 1638, 0, 1641, 0, 1644, 0, 1647, 0,
+ 1650, 0, 1653, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 1656, 1659, 1662,
+ 1665, 1668, 1671, 1674, 1677, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1680, 1683, 1686, 1689, 1692, 1695, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 1698, 1701, 1704,
+ 1707, 1710, 1713, 1716, 1719, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1722, 1725, 1728, 1731, 1734, 1737, 1740, 1743,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 1746, 1749, 1752,
+ 1755, 1758, 1761, 0, 0, 1764, 0, 1771, 0, 1782, 0,
+ 1793, 0, 0, 1804, 0, 1807, 0, 1810, 0, 1813,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 1816, 1819, 1822,
+ 1825, 1828, 1831, 1834, 1837, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1840, 1847, 1854, 1861, 1868, 1875, 1882, 1889, 1840, 1847, 1854,
+ 1861, 1868, 1875, 1882, 1889, 1896, 1903, 1910, 1917, 1924, 1931,
+ 1938, 1945, 1896, 1903, 1910, 1917, 1924, 1931, 1938, 1945,
+ }},
+ {{
+ 1952, 1959, 1966, 1973, 1980, 1987, 1994, 2001, 1952, 1959, 1966,
+ 1973, 1980, 1987, 1994, 2001, 0, 0, 2008, 2015, 2022, 0,
+ 2029, 2036, 2047, 2050, 2053, 2056, 2015, 0, 598, 0,
+ }},
+ {{
+ 0, 0, 2059, 2066, 2073, 0, 2080, 2087, 2098, 2101, 2104,
+ 2107, 2066, 0, 0, 0, 0, 0, 2110, 629, 0, 0,
+ 2121, 2128, 2139, 2142, 2145, 2148, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 2151, 712, 2162, 0, 2169, 2176, 2187, 2190, 2193,
+ 2196, 2199, 0, 0, 0, 0, 0, 2202, 2209, 2216, 0,
+ 2223, 2230, 2241, 2244, 2247, 2250, 2209, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 2253, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 6, 2259, 0, 0, 0, 351, 0, 2265, 0,
+ 16, 16, 16, 0, 0, 18, 18, 24, 0, 0, 28,
+ 2271, 0, 0, 32, 34, 36, 36, 36, 0, 0,
+ }},
+ {{
+ 2277, 2283, 2293, 0, 52, 0, 703, 0, 52, 0, 22,
+ 67, 4, 6, 0, 0, 10, 12, 0, 26, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 646, 679,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2299, 2302, 2305, 2308, 2311, 2314, 2317, 2320, 2323, 2326, 2329,
+ 2332, 2335, 2338, 2341, 2344, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2347, 2350, 2353, 2356, 2359, 2362, 2365, 2368, 2371, 2374,
+ }},
+ {{
+ 2377, 2380, 2383, 2386, 2389, 2392, 2395, 2398, 2401, 2404, 2407,
+ 2410, 2413, 2416, 2419, 2422, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2425, 0, 2435, 0, 2441,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2447, 2453, 2459, 2465, 2471, 2477, 2483, 2489, 0, 0, 2495,
+ 2501, 2507, 0, 0, 0, 2513, 2519, 2529, 2539, 2549, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2447, 2559,
+ 2569, 2579, 0, 0, 0, 0, 0, 0, 0, 2589, 2595,
+ 2601, 2607, 2613, 2607, 2619, 2625, 2631, 2637, 2643, 2637,
+ }},
+ {{
+ 2649, 2656, 0, 2663, 0, 0, 2669, 2683, 2693, 2699, 0,
+ 2705, 0, 2711, 2717, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2723, 0, 2729, 2739, 0, 2745, 2751, 0, 0,
+ }},
+ {{
+ 2757, 2763, 2769, 2775, 2785, 2795, 2795, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2801, 2808, 2815,
+ 2822, 2829, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ }},
+ {{
+ 0, 2836, 2839, 2842, 2845, 2848, 2851, 2854, 2857, 2860, 2863,
+ 2866, 2869, 2872, 2875, 2878, 2881, 2884, 2887, 2890, 2893, 2896,
+ 2899, 2902, 2905, 2908, 2911, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2914, 2918, 2922, 2926, 2930, 2934, 2938, 2942, 2946, 2950, 2954,
+ 2958, 2962, 2966, 2970, 2974, 2978, 2982, 2986, 2990, 2994, 2998,
+ 3002, 3006, 3010, 3014, 3018, 3022, 3026, 3030, 3034, 3038,
+ }},
+ {{
+ 3042, 3046, 3050, 3054, 3058, 3062, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22,
+ 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44,
+ 46, 48, 50, 52, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4,
+ 6, 8, 10, 12, 14, 16, 18, 20, 22, 24,
+ }},
+ {{
+ 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46,
+ 48, 50, 52, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 6,
+ 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28,
+ 30, 32, 34, 36, 38, 40, 42, 44, 46, 48,
+ }},
+ {{
+ 50, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 6, 8,
+ }},
+ {{
+ 0, 0, 14, 0, 0, 20, 22, 0, 0, 28, 30,
+ 32, 34, 0, 38, 40, 42, 44, 46, 48, 50, 52,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 4, 6, 8, 10, 12,
+ 14, 16, 18, 20, 22, 24, 26, 28, 30, 32,
+ }},
+ {{
+ 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 2, 4, 0, 8, 10, 12, 14,
+ 0, 0, 20, 22, 24, 26, 28, 30, 32, 34, 0,
+ 38, 40, 42, 44, 46, 48, 50, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 4, 0, 8, 10, 12, 14, 0,
+ }},
+ {{
+ 18, 20, 22, 24, 26, 0, 30, 0, 0, 0, 38,
+ 40, 42, 44, 46, 48, 50, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20,
+ 22, 24, 26, 28, 30, 32, 34, 36, 38, 40,
+ }},
+ {{
+ 42, 44, 46, 48, 50, 52, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 50, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 4, 6, 8,
+ }},
+ {{
+ 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
+ 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 640, 643, 646,
+ 649, 652, 655, 658, 661, 598, 664, 667, 54, 670, 673,
+ 676, 679, 682, 661, 685, 688, 691, 694, 697, 700,
+ }},
+ {{
+ 703, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 685, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 640, 643, 646, 649, 652, 655, 658, 661, 598,
+ 664, 667, 54, 670, 673, 676, 679, 682, 661, 685, 688,
+ 691, 694, 697, 700, 703, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 685, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 640, 643, 646, 649,
+ }},
+ {{
+ 652, 655, 658, 661, 598, 664, 667, 54, 670, 673, 676,
+ 679, 682, 661, 685, 688, 691, 694, 697, 700, 703, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 685, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 640, 643, 646, 649, 652, 655, 658, 661, 598, 664,
+ }},
+ {{
+ 667, 54, 670, 673, 676, 679, 682, 661, 685, 688, 691,
+ 694, 697, 700, 703, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 685, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 640, 643, 646, 649, 652, 655,
+ 658, 661, 598, 664, 667, 54, 670, 673, 676, 679,
+ }},
+ {{
+ 682, 661, 685, 688, 691, 694, 697, 700, 703, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 685, 0, 0, 0, 0,
+ }},
+};
+
+static const unsigned char nameprep_id11_map_data[] = {
+ 0, 0, 1, 97, 1, 98, 1, 99, 1, 100, 1, 101,
+ 1, 102, 1, 103, 1, 104, 1, 105, 1, 106, 1, 107,
+ 1, 108, 1, 109, 1, 110, 1, 111, 1, 112, 1, 113,
+ 1, 114, 1, 115, 1, 116, 1, 117, 1, 118, 1, 119,
+ 1, 120, 1, 121, 1, 122, 2, 188, 3, 1, 224, 1,
+ 225, 1, 226, 1, 227, 1, 228, 1, 229, 1, 230, 1,
+ 231, 1, 232, 1, 233, 1, 234, 1, 235, 1, 236, 1,
+ 237, 1, 238, 1, 239, 1, 240, 1, 241, 1, 242, 1,
+ 243, 1, 244, 1, 245, 1, 246, 1, 248, 1, 249, 1,
+ 250, 1, 251, 1, 252, 1, 253, 1, 254, 5, 115, 0,
+ 0, 0, 115, 2, 1, 1, 2, 3, 1, 2, 5, 1,
+ 2, 7, 1, 2, 9, 1, 2, 11, 1, 2, 13, 1,
+ 2, 15, 1, 2, 17, 1, 2, 19, 1, 2, 21, 1,
+ 2, 23, 1, 2, 25, 1, 2, 27, 1, 2, 29, 1,
+ 2, 31, 1, 2, 33, 1, 2, 35, 1, 2, 37, 1,
+ 2, 39, 1, 2, 41, 1, 2, 43, 1, 2, 45, 1,
+ 2, 47, 1, 6, 105, 0, 0, 0, 7, 3, 2, 51,
+ 1, 2, 53, 1, 2, 55, 1, 2, 58, 1, 2, 60,
+ 1, 2, 62, 1, 2, 64, 1, 2, 66, 1, 2, 68,
+ 1, 2, 70, 1, 2, 72, 1, 5, 188, 2, 0, 0,
+ 110, 2, 75, 1, 2, 77, 1, 2, 79, 1, 2, 81,
+ 1, 2, 83, 1, 2, 85, 1, 2, 87, 1, 2, 89,
+ 1, 2, 91, 1, 2, 93, 1, 2, 95, 1, 2, 97,
+ 1, 2, 99, 1, 2, 101, 1, 2, 103, 1, 2, 105,
+ 1, 2, 107, 1, 2, 109, 1, 2, 111, 1, 2, 113,
+ 1, 2, 115, 1, 2, 117, 1, 2, 119, 1, 1, 255,
+ 2, 122, 1, 2, 124, 1, 2, 126, 1, 2, 83, 2,
+ 2, 131, 1, 2, 133, 1, 2, 84, 2, 2, 136, 1,
+ 2, 86, 2, 2, 87, 2, 2, 140, 1, 2, 221, 1,
+ 2, 89, 2, 2, 91, 2, 2, 146, 1, 2, 96, 2,
+ 2, 99, 2, 2, 105, 2, 2, 104, 2, 2, 153, 1,
+ 2, 111, 2, 2, 114, 2, 2, 117, 2, 2, 161, 1,
+ 2, 163, 1, 2, 165, 1, 2, 128, 2, 2, 168, 1,
+ 2, 131, 2, 2, 173, 1, 2, 136, 2, 2, 176, 1,
+ 2, 138, 2, 2, 139, 2, 2, 180, 1, 2, 182, 1,
+ 2, 146, 2, 2, 185, 1, 2, 189, 1, 2, 198, 1,
+ 2, 201, 1, 2, 204, 1, 2, 206, 1, 2, 208, 1,
+ 2, 210, 1, 2, 212, 1, 2, 214, 1, 2, 216, 1,
+ 2, 218, 1, 2, 220, 1, 2, 223, 1, 2, 225, 1,
+ 2, 227, 1, 2, 229, 1, 2, 231, 1, 2, 233, 1,
+ 2, 235, 1, 2, 237, 1, 2, 239, 1, 6, 106, 0,
+ 0, 0, 12, 3, 2, 243, 1, 2, 245, 1, 2, 149,
+ 1, 2, 191, 1, 2, 249, 1, 2, 251, 1, 2, 253,
+ 1, 2, 255, 1, 2, 1, 2, 2, 3, 2, 2, 5,
+ 2, 2, 7, 2, 2, 9, 2, 2, 11, 2, 2, 13,
+ 2, 2, 15, 2, 2, 17, 2, 2, 19, 2, 2, 21,
+ 2, 2, 23, 2, 2, 25, 2, 2, 27, 2, 2, 29,
+ 2, 2, 31, 2, 2, 158, 1, 2, 35, 2, 2, 37,
+ 2, 2, 39, 2, 2, 41, 2, 2, 43, 2, 2, 45,
+ 2, 2, 47, 2, 2, 49, 2, 2, 51, 2, 2, 185,
+ 3, 6, 32, 0, 0, 0, 185, 3, 2, 172, 3, 2,
+ 173, 3, 2, 174, 3, 2, 175, 3, 2, 204, 3, 2,
+ 205, 3, 2, 206, 3, 10, 185, 3, 0, 0, 8, 3,
+ 0, 0, 1, 3, 2, 177, 3, 2, 178, 3, 2, 179,
+ 3, 2, 180, 3, 2, 181, 3, 2, 182, 3, 2, 183,
+ 3, 2, 184, 3, 2, 186, 3, 2, 187, 3, 2, 189,
+ 3, 2, 190, 3, 2, 191, 3, 2, 192, 3, 2, 193,
+ 3, 2, 195, 3, 2, 196, 3, 2, 197, 3, 2, 198,
+ 3, 2, 199, 3, 2, 200, 3, 2, 201, 3, 2, 202,
+ 3, 2, 203, 3, 10, 197, 3, 0, 0, 8, 3, 0,
+ 0, 1, 3, 2, 217, 3, 2, 219, 3, 2, 221, 3,
+ 2, 223, 3, 2, 225, 3, 2, 227, 3, 2, 229, 3,
+ 2, 231, 3, 2, 233, 3, 2, 235, 3, 2, 237, 3,
+ 2, 239, 3, 2, 80, 4, 2, 81, 4, 2, 82, 4,
+ 2, 83, 4, 2, 84, 4, 2, 85, 4, 2, 86, 4,
+ 2, 87, 4, 2, 88, 4, 2, 89, 4, 2, 90, 4,
+ 2, 91, 4, 2, 92, 4, 2, 93, 4, 2, 94, 4,
+ 2, 95, 4, 2, 48, 4, 2, 49, 4, 2, 50, 4,
+ 2, 51, 4, 2, 52, 4, 2, 53, 4, 2, 54, 4,
+ 2, 55, 4, 2, 56, 4, 2, 57, 4, 2, 58, 4,
+ 2, 59, 4, 2, 60, 4, 2, 61, 4, 2, 62, 4,
+ 2, 63, 4, 2, 64, 4, 2, 65, 4, 2, 66, 4,
+ 2, 67, 4, 2, 68, 4, 2, 69, 4, 2, 70, 4,
+ 2, 71, 4, 2, 72, 4, 2, 73, 4, 2, 74, 4,
+ 2, 75, 4, 2, 76, 4, 2, 77, 4, 2, 78, 4,
+ 2, 79, 4, 2, 97, 4, 2, 99, 4, 2, 101, 4,
+ 2, 103, 4, 2, 105, 4, 2, 107, 4, 2, 109, 4,
+ 2, 111, 4, 2, 113, 4, 2, 115, 4, 2, 117, 4,
+ 2, 119, 4, 2, 121, 4, 2, 123, 4, 2, 125, 4,
+ 2, 127, 4, 2, 129, 4, 2, 139, 4, 2, 141, 4,
+ 2, 143, 4, 2, 145, 4, 2, 147, 4, 2, 149, 4,
+ 2, 151, 4, 2, 153, 4, 2, 155, 4, 2, 157, 4,
+ 2, 159, 4, 2, 161, 4, 2, 163, 4, 2, 165, 4,
+ 2, 167, 4, 2, 169, 4, 2, 171, 4, 2, 173, 4,
+ 2, 175, 4, 2, 177, 4, 2, 179, 4, 2, 181, 4,
+ 2, 183, 4, 2, 185, 4, 2, 187, 4, 2, 189, 4,
+ 2, 191, 4, 2, 194, 4, 2, 196, 4, 2, 198, 4,
+ 2, 200, 4, 2, 202, 4, 2, 204, 4, 2, 206, 4,
+ 2, 209, 4, 2, 211, 4, 2, 213, 4, 2, 215, 4,
+ 2, 217, 4, 2, 219, 4, 2, 221, 4, 2, 223, 4,
+ 2, 225, 4, 2, 227, 4, 2, 229, 4, 2, 231, 4,
+ 2, 233, 4, 2, 235, 4, 2, 237, 4, 2, 239, 4,
+ 2, 241, 4, 2, 243, 4, 2, 245, 4, 2, 249, 4,
+ 2, 1, 5, 2, 3, 5, 2, 5, 5, 2, 7, 5,
+ 2, 9, 5, 2, 11, 5, 2, 13, 5, 2, 15, 5,
+ 2, 97, 5, 2, 98, 5, 2, 99, 5, 2, 100, 5,
+ 2, 101, 5, 2, 102, 5, 2, 103, 5, 2, 104, 5,
+ 2, 105, 5, 2, 106, 5, 2, 107, 5, 2, 108, 5,
+ 2, 109, 5, 2, 110, 5, 2, 111, 5, 2, 112, 5,
+ 2, 113, 5, 2, 114, 5, 2, 115, 5, 2, 116, 5,
+ 2, 117, 5, 2, 118, 5, 2, 119, 5, 2, 120, 5,
+ 2, 121, 5, 2, 122, 5, 2, 123, 5, 2, 124, 5,
+ 2, 125, 5, 2, 126, 5, 2, 127, 5, 2, 128, 5,
+ 2, 129, 5, 2, 130, 5, 2, 131, 5, 2, 132, 5,
+ 2, 133, 5, 2, 134, 5, 6, 101, 5, 0, 0, 130,
+ 5, 2, 1, 30, 2, 3, 30, 2, 5, 30, 2, 7,
+ 30, 2, 9, 30, 2, 11, 30, 2, 13, 30, 2, 15,
+ 30, 2, 17, 30, 2, 19, 30, 2, 21, 30, 2, 23,
+ 30, 2, 25, 30, 2, 27, 30, 2, 29, 30, 2, 31,
+ 30, 2, 33, 30, 2, 35, 30, 2, 37, 30, 2, 39,
+ 30, 2, 41, 30, 2, 43, 30, 2, 45, 30, 2, 47,
+ 30, 2, 49, 30, 2, 51, 30, 2, 53, 30, 2, 55,
+ 30, 2, 57, 30, 2, 59, 30, 2, 61, 30, 2, 63,
+ 30, 2, 65, 30, 2, 67, 30, 2, 69, 30, 2, 71,
+ 30, 2, 73, 30, 2, 75, 30, 2, 77, 30, 2, 79,
+ 30, 2, 81, 30, 2, 83, 30, 2, 85, 30, 2, 87,
+ 30, 2, 89, 30, 2, 91, 30, 2, 93, 30, 2, 95,
+ 30, 2, 97, 30, 2, 99, 30, 2, 101, 30, 2, 103,
+ 30, 2, 105, 30, 2, 107, 30, 2, 109, 30, 2, 111,
+ 30, 2, 113, 30, 2, 115, 30, 2, 117, 30, 2, 119,
+ 30, 2, 121, 30, 2, 123, 30, 2, 125, 30, 2, 127,
+ 30, 2, 129, 30, 2, 131, 30, 2, 133, 30, 2, 135,
+ 30, 2, 137, 30, 2, 139, 30, 2, 141, 30, 2, 143,
+ 30, 2, 145, 30, 2, 147, 30, 2, 149, 30, 6, 104,
+ 0, 0, 0, 49, 3, 6, 116, 0, 0, 0, 8, 3,
+ 6, 119, 0, 0, 0, 10, 3, 6, 121, 0, 0, 0,
+ 10, 3, 6, 97, 0, 0, 0, 190, 2, 2, 161, 30,
+ 2, 163, 30, 2, 165, 30, 2, 167, 30, 2, 169, 30,
+ 2, 171, 30, 2, 173, 30, 2, 175, 30, 2, 177, 30,
+ 2, 179, 30, 2, 181, 30, 2, 183, 30, 2, 185, 30,
+ 2, 187, 30, 2, 189, 30, 2, 191, 30, 2, 193, 30,
+ 2, 195, 30, 2, 197, 30, 2, 199, 30, 2, 201, 30,
+ 2, 203, 30, 2, 205, 30, 2, 207, 30, 2, 209, 30,
+ 2, 211, 30, 2, 213, 30, 2, 215, 30, 2, 217, 30,
+ 2, 219, 30, 2, 221, 30, 2, 223, 30, 2, 225, 30,
+ 2, 227, 30, 2, 229, 30, 2, 231, 30, 2, 233, 30,
+ 2, 235, 30, 2, 237, 30, 2, 239, 30, 2, 241, 30,
+ 2, 243, 30, 2, 245, 30, 2, 247, 30, 2, 249, 30,
+ 2, 0, 31, 2, 1, 31, 2, 2, 31, 2, 3, 31,
+ 2, 4, 31, 2, 5, 31, 2, 6, 31, 2, 7, 31,
+ 2, 16, 31, 2, 17, 31, 2, 18, 31, 2, 19, 31,
+ 2, 20, 31, 2, 21, 31, 2, 32, 31, 2, 33, 31,
+ 2, 34, 31, 2, 35, 31, 2, 36, 31, 2, 37, 31,
+ 2, 38, 31, 2, 39, 31, 2, 48, 31, 2, 49, 31,
+ 2, 50, 31, 2, 51, 31, 2, 52, 31, 2, 53, 31,
+ 2, 54, 31, 2, 55, 31, 2, 64, 31, 2, 65, 31,
+ 2, 66, 31, 2, 67, 31, 2, 68, 31, 2, 69, 31,
+ 6, 197, 3, 0, 0, 19, 3, 10, 197, 3, 0, 0,
+ 19, 3, 0, 0, 0, 3, 10, 197, 3, 0, 0, 19,
+ 3, 0, 0, 1, 3, 10, 197, 3, 0, 0, 19, 3,
+ 0, 0, 66, 3, 2, 81, 31, 2, 83, 31, 2, 85,
+ 31, 2, 87, 31, 2, 96, 31, 2, 97, 31, 2, 98,
+ 31, 2, 99, 31, 2, 100, 31, 2, 101, 31, 2, 102,
+ 31, 2, 103, 31, 6, 0, 31, 0, 0, 185, 3, 6,
+ 1, 31, 0, 0, 185, 3, 6, 2, 31, 0, 0, 185,
+ 3, 6, 3, 31, 0, 0, 185, 3, 6, 4, 31, 0,
+ 0, 185, 3, 6, 5, 31, 0, 0, 185, 3, 6, 6,
+ 31, 0, 0, 185, 3, 6, 7, 31, 0, 0, 185, 3,
+ 6, 32, 31, 0, 0, 185, 3, 6, 33, 31, 0, 0,
+ 185, 3, 6, 34, 31, 0, 0, 185, 3, 6, 35, 31,
+ 0, 0, 185, 3, 6, 36, 31, 0, 0, 185, 3, 6,
+ 37, 31, 0, 0, 185, 3, 6, 38, 31, 0, 0, 185,
+ 3, 6, 39, 31, 0, 0, 185, 3, 6, 96, 31, 0,
+ 0, 185, 3, 6, 97, 31, 0, 0, 185, 3, 6, 98,
+ 31, 0, 0, 185, 3, 6, 99, 31, 0, 0, 185, 3,
+ 6, 100, 31, 0, 0, 185, 3, 6, 101, 31, 0, 0,
+ 185, 3, 6, 102, 31, 0, 0, 185, 3, 6, 103, 31,
+ 0, 0, 185, 3, 6, 112, 31, 0, 0, 185, 3, 6,
+ 177, 3, 0, 0, 185, 3, 6, 172, 3, 0, 0, 185,
+ 3, 6, 177, 3, 0, 0, 66, 3, 10, 177, 3, 0,
+ 0, 66, 3, 0, 0, 185, 3, 2, 176, 31, 2, 177,
+ 31, 2, 112, 31, 2, 113, 31, 6, 116, 31, 0, 0,
+ 185, 3, 6, 183, 3, 0, 0, 185, 3, 6, 174, 3,
+ 0, 0, 185, 3, 6, 183, 3, 0, 0, 66, 3, 10,
+ 183, 3, 0, 0, 66, 3, 0, 0, 185, 3, 2, 114,
+ 31, 2, 115, 31, 2, 116, 31, 2, 117, 31, 10, 185,
+ 3, 0, 0, 8, 3, 0, 0, 0, 3, 6, 185, 3,
+ 0, 0, 66, 3, 10, 185, 3, 0, 0, 8, 3, 0,
+ 0, 66, 3, 2, 208, 31, 2, 209, 31, 2, 118, 31,
+ 2, 119, 31, 10, 197, 3, 0, 0, 8, 3, 0, 0,
+ 0, 3, 6, 193, 3, 0, 0, 19, 3, 6, 197, 3,
+ 0, 0, 66, 3, 10, 197, 3, 0, 0, 8, 3, 0,
+ 0, 66, 3, 2, 224, 31, 2, 225, 31, 2, 122, 31,
+ 2, 123, 31, 2, 229, 31, 6, 124, 31, 0, 0, 185,
+ 3, 6, 201, 3, 0, 0, 185, 3, 6, 206, 3, 0,
+ 0, 185, 3, 6, 201, 3, 0, 0, 66, 3, 10, 201,
+ 3, 0, 0, 66, 3, 0, 0, 185, 3, 2, 120, 31,
+ 2, 121, 31, 2, 124, 31, 2, 125, 31, 5, 114, 0,
+ 0, 0, 115, 5, 176, 0, 0, 0, 99, 5, 176, 0,
+ 0, 0, 102, 5, 110, 0, 0, 0, 111, 5, 115, 0,
+ 0, 0, 109, 9, 116, 0, 0, 0, 101, 0, 0, 0,
+ 108, 5, 116, 0, 0, 0, 109, 2, 112, 33, 2, 113,
+ 33, 2, 114, 33, 2, 115, 33, 2, 116, 33, 2, 117,
+ 33, 2, 118, 33, 2, 119, 33, 2, 120, 33, 2, 121,
+ 33, 2, 122, 33, 2, 123, 33, 2, 124, 33, 2, 125,
+ 33, 2, 126, 33, 2, 127, 33, 2, 208, 36, 2, 209,
+ 36, 2, 210, 36, 2, 211, 36, 2, 212, 36, 2, 213,
+ 36, 2, 214, 36, 2, 215, 36, 2, 216, 36, 2, 217,
+ 36, 2, 218, 36, 2, 219, 36, 2, 220, 36, 2, 221,
+ 36, 2, 222, 36, 2, 223, 36, 2, 224, 36, 2, 225,
+ 36, 2, 226, 36, 2, 227, 36, 2, 228, 36, 2, 229,
+ 36, 2, 230, 36, 2, 231, 36, 2, 232, 36, 2, 233,
+ 36, 9, 104, 0, 0, 0, 112, 0, 0, 0, 97, 5,
+ 97, 0, 0, 0, 117, 5, 111, 0, 0, 0, 118, 5,
+ 112, 0, 0, 0, 97, 5, 110, 0, 0, 0, 97, 5,
+ 188, 3, 0, 0, 97, 5, 109, 0, 0, 0, 97, 5,
+ 107, 0, 0, 0, 97, 5, 107, 0, 0, 0, 98, 5,
+ 109, 0, 0, 0, 98, 5, 103, 0, 0, 0, 98, 5,
+ 112, 0, 0, 0, 102, 5, 110, 0, 0, 0, 102, 5,
+ 188, 3, 0, 0, 102, 5, 104, 0, 0, 0, 122, 9,
+ 107, 0, 0, 0, 104, 0, 0, 0, 122, 9, 109, 0,
+ 0, 0, 104, 0, 0, 0, 122, 9, 103, 0, 0, 0,
+ 104, 0, 0, 0, 122, 9, 116, 0, 0, 0, 104, 0,
+ 0, 0, 122, 9, 107, 0, 0, 0, 112, 0, 0, 0,
+ 97, 9, 109, 0, 0, 0, 112, 0, 0, 0, 97, 9,
+ 103, 0, 0, 0, 112, 0, 0, 0, 97, 5, 112, 0,
+ 0, 0, 118, 5, 110, 0, 0, 0, 118, 5, 188, 3,
+ 0, 0, 118, 5, 109, 0, 0, 0, 118, 5, 107, 0,
+ 0, 0, 118, 5, 112, 0, 0, 0, 119, 5, 110, 0,
+ 0, 0, 119, 5, 188, 3, 0, 0, 119, 5, 109, 0,
+ 0, 0, 119, 5, 107, 0, 0, 0, 119, 6, 107, 0,
+ 0, 0, 201, 3, 6, 109, 0, 0, 0, 201, 3, 5,
+ 98, 0, 0, 0, 113, 13, 99, 0, 0, 0, 21, 34,
+ 0, 0, 107, 0, 0, 0, 103, 9, 99, 0, 0, 0,
+ 111, 0, 0, 0, 46, 5, 100, 0, 0, 0, 98, 5,
+ 103, 0, 0, 0, 121, 5, 104, 0, 0, 0, 112, 5,
+ 107, 0, 0, 0, 107, 5, 107, 0, 0, 0, 109, 5,
+ 112, 0, 0, 0, 104, 9, 112, 0, 0, 0, 112, 0,
+ 0, 0, 109, 5, 112, 0, 0, 0, 114, 5, 115, 0,
+ 0, 0, 118, 5, 119, 0, 0, 0, 98, 5, 102, 0,
+ 0, 0, 102, 5, 102, 0, 0, 0, 105, 5, 102, 0,
+ 0, 0, 108, 9, 102, 0, 0, 0, 102, 0, 0, 0,
+ 105, 9, 102, 0, 0, 0, 102, 0, 0, 0, 108, 5,
+ 115, 0, 0, 0, 116, 6, 116, 5, 0, 0, 118, 5,
+ 6, 116, 5, 0, 0, 101, 5, 6, 116, 5, 0, 0,
+ 107, 5, 6, 126, 5, 0, 0, 118, 5, 6, 116, 5,
+ 0, 0, 109, 5, 2, 65, 255, 2, 66, 255, 2, 67,
+ 255, 2, 68, 255, 2, 69, 255, 2, 70, 255, 2, 71,
+ 255, 2, 72, 255, 2, 73, 255, 2, 74, 255, 2, 75,
+ 255, 2, 76, 255, 2, 77, 255, 2, 78, 255, 2, 79,
+ 255, 2, 80, 255, 2, 81, 255, 2, 82, 255, 2, 83,
+ 255, 2, 84, 255, 2, 85, 255, 2, 86, 255, 2, 87,
+ 255, 2, 88, 255, 2, 89, 255, 2, 90, 255, 3, 40,
+ 4, 1, 3, 41, 4, 1, 3, 42, 4, 1, 3, 43,
+ 4, 1, 3, 44, 4, 1, 3, 45, 4, 1, 3, 46,
+ 4, 1, 3, 47, 4, 1, 3, 48, 4, 1, 3, 49,
+ 4, 1, 3, 50, 4, 1, 3, 51, 4, 1, 3, 52,
+ 4, 1, 3, 53, 4, 1, 3, 54, 4, 1, 3, 55,
+ 4, 1, 3, 56, 4, 1, 3, 57, 4, 1, 3, 58,
+ 4, 1, 3, 59, 4, 1, 3, 60, 4, 1, 3, 61,
+ 4, 1, 3, 62, 4, 1, 3, 63, 4, 1, 3, 64,
+ 4, 1, 3, 65, 4, 1, 3, 66, 4, 1, 3, 67,
+ 4, 1, 3, 68, 4, 1, 3, 69, 4, 1, 3, 70,
+ 4, 1, 3, 71, 4, 1, 3, 72, 4, 1, 3, 73,
+ 4, 1, 3, 74, 4, 1, 3, 75, 4, 1, 3, 76,
+ 4, 1, 3, 77, 4, 1,
+};
+
+static const unsigned short nameprep_id11_prohibited_imap[] = {
+ 68, 196, 196, 324, 196, 196, 196, 452,
+ 196, 196, 196, 580, 196, 196, 196, 580,
+ 196, 196, 196, 580, 196, 196, 196, 580,
+ 196, 196, 196, 580, 196, 196, 196, 580,
+ 196, 196, 196, 580, 196, 196, 196, 580,
+ 196, 196, 196, 580, 196, 196, 196, 580,
+ 196, 196, 196, 580, 196, 196, 196, 580,
+ 708, 196, 196, 580, 836, 836, 836, 836,
+ 836, 836, 836, 836, 0, 1, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 3, 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 5, 0, 0, 6, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 8, 5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 10,
+ 0, 0, 0, 11, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 12, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 13, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 13, 14, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9,
+};
+
+static const struct {
+ unsigned char bm[16];
+} nameprep_id11_prohibited_bitmap[] = {
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 255,255,255,255, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0,
+ }},
+ {{
+ 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 255,199, 0, 0, 0,255, 0, 0, 0, 0, 0,128, 14,252, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255, 15,
+ }},
+ {{
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255,255,255, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,248, 7,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,
+ }},
+ {{
+ 2, 0, 0, 0,255,255,255,255,255,255,255,255,255,255,255,255,
+ }},
+};
+
+static const unsigned short nameprep_id11_unassigned_imap[] = {
+ 68, 196, 324, 452, 580, 708, 708, 836,
+ 964, 964, 1092, 1220, 708, 708, 708, 1348,
+ 708, 708, 708, 1348, 708, 708, 708, 1348,
+ 708, 708, 708, 1348, 708, 708, 708, 1348,
+ 708, 708, 708, 1348, 708, 708, 708, 1348,
+ 708, 708, 708, 1348, 708, 708, 708, 1348,
+ 708, 708, 708, 1348, 708, 708, 708, 1348,
+ 1476, 708, 708, 1348, 964, 964, 964, 964,
+ 964, 964, 964, 964, 0, 0, 0, 0,
+ 1, 2, 3, 4, 0, 5, 6, 7,
+ 8, 9, 10, 11, 12, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 0, 0, 0,
+ 36, 37, 38, 39, 40, 41, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 0, 42, 43, 44, 45, 46, 47, 48,
+ 0, 0, 0, 49, 50, 51, 0, 0,
+ 52, 53, 54, 55, 0, 0, 0, 0,
+ 0, 0, 12, 12, 12, 12, 12, 12,
+ 12, 56, 0, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 66,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 67, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 68, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 69, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 70, 12, 71, 72, 0, 0, 73, 74,
+ 75, 76, 35, 77, 12, 12, 12, 12,
+ 12, 12, 78, 12, 79, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 0, 80, 81, 82,
+ 12, 12, 12, 12, 83, 84, 85, 0,
+ 0, 86, 0, 87, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 88, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 89, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 0, 0, 0, 0,
+ 90, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 88, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 88, 91, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12,
+};
+
+static const struct {
+ unsigned char bm[16];
+} nameprep_id11_unassigned_bitmap[] = {
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 2, 0,240,255,255,255, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0,192, 0, 0, 0, 0, 0, 0, 0,128,255,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,255, 0, 0,207,187,
+ }},
+ {{
+ 15, 40, 0, 0, 4, 0, 0, 0, 0,128, 0, 0, 0, 0,128,255,
+ }},
+ {{
+ 128, 0, 0, 0, 0, 0, 0, 0, 0,128, 0, 0, 0, 0,192,252,
+ }},
+ {{
+ 0, 0,255,255,255,255, 1, 0, 0, 0,128, 1, 1, 0, 0, 0,
+ }},
+ {{
+ 0,249, 1, 0, 4, 0, 0, 4,224,255, 0, 0, 0,248,224,255,
+ }},
+ {{
+ 255,239,255,119, 1, 0, 0,248, 0, 0,192,255, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 0,128,
+ }},
+ {{
+ 0, 64, 0, 0, 0,224, 0, 0, 0,248,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0,252,255,255,255,255,255,255,255,255,255,
+ }},
+ {{
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ }},
+ {{
+ 17, 0, 0, 0, 0, 0, 0, 12, 0,192,224, 0, 0, 0,254,255,
+ }},
+ {{
+ 17, 96, 6, 0, 0, 2, 58, 44, 96,198,127, 79, 48, 0, 0,248,
+ }},
+ {{
+ 27,120, 6, 0, 0, 2,146, 44,120,198,255,161, 63, 0,224,255,
+ }},
+ {{
+ 17, 80, 4, 0, 0, 2, 18, 12, 64,196,254,255, 62, 0,255,255,
+ }},
+ {{
+ 17, 96, 6, 0, 0, 2, 50, 12,112,198, 63, 79, 60, 0,254,255,
+ }},
+ {{
+ 19, 56,194, 41,231, 56, 64, 60, 56,194,127,255,127, 0,248,255,
+ }},
+ {{
+ 17, 32, 2, 0, 0, 2, 16, 60, 32,194,159,255, 60, 0,255,255,
+ }},
+ {{
+ 19, 32, 2, 0, 0, 2, 16, 60, 32,194,159,191, 60, 0,255,255,
+ }},
+ {{
+ 19, 32, 2, 0, 0, 2, 0, 60, 48,194,127,255, 60, 0,255,255,
+ }},
+ {{
+ 19, 0,128, 3, 0, 0, 4,208,128,123,160, 0,255,255,227,255,
+ }},
+ {{
+ 1, 0, 0, 0, 0, 0, 0,120, 0, 0, 0,240,255,255,255,255,
+ }},
+ {{
+ 105,218, 15, 1, 81, 19, 0,196,160,192, 0,204,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,248, 1, 0,
+ }},
+ {{
+ 0,240, 0, 1, 0, 0, 0, 32, 0, 96,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0, 4, 9, 56,252, 0, 0, 0,252,255,255,255,255,
+ }},
+ {{
+ 255,255,255,255, 0, 0, 0, 0,192,255, 0, 0, 0, 0, 0,246,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,124, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0,248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252,
+ }},
+ {{
+ 128, 0, 0, 0, 0, 0, 0, 0,128,194,128,194, 0, 0, 0, 0,
+ }},
+ {{
+ 128,194, 0, 0, 0,128,194,128,194,128,128, 0, 0,128, 0, 0,
+ }},
+ {{
+ 0,128,194,128, 0, 0, 0, 0,128, 0, 0,248, 1, 0, 0,224,
+ }},
+ {{
+ 255,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,224,255,
+ }},
+ {{
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,255,
+ }},
+ {{
+ 0, 0, 0,224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,254,255,
+ }},
+ {{
+ 0, 32,224,255, 0, 0,128,255, 0, 0,240,255, 0, 32,242,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,224, 0,252,255,255,
+ }},
+ {{
+ 0,128, 0,252, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0,252,255,255,255,255,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0,240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,252,
+ }},
+ {{
+ 0, 0,192,192, 0, 0, 0, 0,192,192, 0, 85, 0, 0, 0,192,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 32, 0, 32, 0, 48, 16, 0, 0, 35,128,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,120,127,240, 3, 12, 0,
+ }},
+ {{
+ 0,128,255,255, 0, 0,252,255,255,255, 0, 0, 0,248,255,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 24, 0,240, 7, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 240,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,128,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0,128,255,255,255, 0,248,255,255, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,
+ }},
+ {{
+ 0, 0, 48, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,
+ }},
+ {{
+ 0,252,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+ }},
+ {{
+ 33, 12, 0, 0, 0, 1, 0, 0, 0, 80,184,128, 1, 0, 0, 0,
+ }},
+ {{
+ 0, 0,224, 0, 0, 0, 1,128,255,255, 0, 0, 0,240, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,255,255,255, 0,240,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0,128, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 31, 0, 0, 0, 0,224, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0,128, 0, 0, 0, 0, 0,255,255,255,255,255,255,255, 0, 0,
+ }},
+ {{
+ 0, 0, 0,224, 0, 0, 0, 0,240,255, 1, 0, 0, 0, 0,112,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,240, 0, 0, 0, 0, 0,128,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128, 7,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192, 0, 0, 0,128,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0,192,255,255,255,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0,192,255,255,255,255,255,255,255,255,255,255,255,
+ }},
+ {{
+ 0,224, 0, 0, 0, 0, 0, 0,128,255,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0,240,255,255,255,255,255,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0,192, 0, 0, 0, 0, 0, 0, 0,248,255,255,
+ }},
+ {{
+ 128,255, 7, 31, 0, 0,128,160, 36, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0,252,255,255,255, 7, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0,255,255, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 3, 0, 0, 0, 0, 0, 0,255, 0, 0, 0, 0, 0,224,
+ }},
+ {{
+ 0, 0,255,255,240,255, 0, 0,128, 1, 8, 0,128,240, 32, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0,128, 3, 3, 3,227,128,128,255, 1,
+ }},
+ {{
+ 0, 0, 0,128,240,255, 0, 0, 0,248,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0,192, 0, 0, 0, 0,192,255,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,255,
+ }},
+ {{
+ 0, 0, 0, 0,128, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,192,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 32,155, 33, 0, 20, 18, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 64, 24, 32, 32, 0, 0, 0,132,160, 3, 2, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0,240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 63,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,128,255,255,255,255,255,
+ }},
+ {{
+ 0, 0, 0,192,255,255,255,255,255,255,255,255,255,255,255,255,
+ }},
+ {{
+ 253,255,255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+};
+
+static const unsigned short nameprep_id11_bidi_imap[] = {
+ 272, 400, 528, 656, 784, 912, 912, 912,
+ 912, 1040, 1168, 912, 912, 1296, 912, 1424,
+ 1552, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1808, 1680, 1680,
+ 912, 912, 912, 912, 912, 912, 912, 912,
+ 912, 912, 1936, 1680, 1680, 1680, 1680, 2064,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680,
+ 912, 912, 912, 912, 912, 912, 912, 912,
+ 912, 912, 912, 912, 912, 912, 912, 2192,
+ 912, 912, 912, 912, 912, 912, 912, 912,
+ 912, 912, 912, 912, 912, 912, 912, 2192,
+ 0, 0, 1, 1, 0, 2, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 5, 6, 4, 4, 7, 8, 9,
+ 0, 0, 0, 10, 11, 12, 13, 14,
+ 4, 4, 4, 4, 15, 4, 13, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 29, 30, 31,
+ 32, 33, 0, 0, 29, 34, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 35, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50,
+ 39, 51, 41, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 60,
+ 61, 64, 65, 60, 66, 67, 68, 69,
+ 20, 70, 71, 0, 72, 73, 74, 0,
+ 75, 76, 77, 78, 79, 80, 81, 0,
+ 4, 82, 83, 0, 0, 4, 84, 85,
+ 4, 4, 86, 4, 4, 87, 4, 88,
+ 89, 4, 90, 4, 91, 92, 93, 13,
+ 92, 4, 94, 95, 0, 4, 4, 96,
+ 20, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 97, 1, 4, 4, 98,
+ 99, 100, 101, 102, 4, 103, 104, 105,
+ 106, 4, 4, 83, 4, 107, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 4, 4, 108, 4, 4, 88,
+ 109, 4, 110, 111, 4, 112, 113, 114,
+ 115, 0, 0, 116, 0, 0, 0, 0,
+ 117, 118, 119, 4, 120, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 121, 4, 122, 123, 0, 0, 0,
+ 0, 0, 0, 0, 124, 4, 4, 105,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 125, 126, 20, 4, 127, 20, 4, 128,
+ 129, 130, 4, 4, 13, 83, 0, 6,
+ 131, 4, 120, 132, 4, 98, 133, 134,
+ 4, 4, 4, 135, 4, 4, 111, 134,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 14, 0, 0,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 136, 0, 0,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 137, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 120, 0, 0,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 138, 4, 139, 0, 0, 0, 0,
+ 140, 141, 142, 29, 29, 143, 144, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 145, 146, 29, 147, 29, 148, 149,
+ 0, 0, 0, 150, 29, 29, 29, 151,
+ 0, 1, 1, 152, 4, 134, 153, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 134, 154, 139, 0, 0, 0, 0, 0,
+ 4, 155, 156, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 4, 4, 4, 4, 4, 14,
+ 4, 157, 4, 158, 159, 160, 111, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 161, 4, 162, 163, 164, 4,
+ 165, 166, 167, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 168, 4, 4,
+ 4, 4, 4, 4, 4, 4, 105, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 97, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 111, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 111,
+};
+
+static const struct {
+ unsigned char tbl[32];
+} nameprep_id11_bidi_table[] = {
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 2, 0, 2, 2, 2, 0, 2, 0, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ }},
+ {{
+ 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
+ }},
+ {{
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2,
+ }},
+ {{
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2,
+ 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2,
+ 0, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2,
+ }},
+ {{
+ 2, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 2, 0, 2,
+ }},
+ {{
+ 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2,
+ 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2,
+ 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 0, 0, 0, 2, 2,
+ }},
+ {{
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
+ 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2,
+ 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2,
+ 0, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2,
+ }},
+ {{
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2,
+ 0, 2, 2, 0, 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 0,
+ }},
+ {{
+ 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 2, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2,
+ 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 0, 2, 0, 2, 2,
+ }},
+ {{
+ 0, 0, 0, 2, 2, 0, 0, 0, 2, 2, 2, 0, 0, 0, 2, 2, 2,
+ 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 2, 2,
+ }},
+ {{
+ 0, 2, 2, 0, 0, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2,
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2,
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 0, 0, 2, 2, 0, 2, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2,
+ }},
+ {{
+ 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2,
+ 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 2, 0, 2, 0, 0, 2, 2, 0, 2, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 0, 2, 2, 2, 0, 2, 0, 2, 0, 0, 2, 2, 0, 2, 2, 2, 2,
+ 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 2, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 0, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2,
+ }},
+ {{
+ 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2, 2, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2,
+ 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0,
+ }},
+ {{
+ 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2,
+ 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2,
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 0, 2, 0, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0,
+ }},
+ {{
+ 0, 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2,
+ 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0,
+ 0, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ }},
+ {{
+ 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 2, 2, 2, 2, 0, 2, 2,
+ 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 1, 0, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0,
+ }},
+ {{
+ 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ }},
+ {{
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 0,
+ 0, 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ }},
+ {{
+ 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2,
+ }},
+ {{
+ 0, 0, 2, 0, 0, 2, 2, 0, 0, 2, 2, 2, 2, 0, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0, 2, 2, 2,
+ }},
+ {{
+ 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2,
+ 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0,
+ }},
+ {{
+ 2, 2, 2, 2, 2, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+ {{
+ 2, 2, 2, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ }},
+};
+
+static const unsigned char nameprep_id11_bidi_data[] = {
+ idn_biditype_others,
+ idn_biditype_r_al,
+ idn_biditype_l,
+};
+
diff --git a/netwerk/dns/nsDNSService2.cpp b/netwerk/dns/nsDNSService2.cpp
new file mode 100644
index 000000000..05831139e
--- /dev/null
+++ b/netwerk/dns/nsDNSService2.cpp
@@ -0,0 +1,1071 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set sw=4 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsDNSService2.h"
+#include "nsIDNSRecord.h"
+#include "nsIDNSListener.h"
+#include "nsICancelable.h"
+#include "nsIPrefService.h"
+#include "nsIPrefBranch.h"
+#include "nsIServiceManager.h"
+#include "nsIXPConnect.h"
+#include "nsProxyRelease.h"
+#include "nsReadableUtils.h"
+#include "nsString.h"
+#include "nsAutoPtr.h"
+#include "nsNetCID.h"
+#include "nsError.h"
+#include "nsDNSPrefetch.h"
+#include "nsThreadUtils.h"
+#include "nsIProtocolProxyService.h"
+#include "prsystem.h"
+#include "prnetdb.h"
+#include "prmon.h"
+#include "prio.h"
+#include "plstr.h"
+#include "nsIOService.h"
+#include "nsCharSeparatedTokenizer.h"
+#include "nsNetAddr.h"
+#include "nsProxyRelease.h"
+#include "nsIObserverService.h"
+#include "nsINetworkLinkService.h"
+
+#include "mozilla/Attributes.h"
+#include "mozilla/net/NeckoCommon.h"
+#include "mozilla/net/ChildDNSService.h"
+#include "mozilla/net/DNSListenerProxy.h"
+#include "mozilla/Services.h"
+
+using namespace mozilla;
+using namespace mozilla::net;
+
+static const char kPrefDnsCacheEntries[] = "network.dnsCacheEntries";
+static const char kPrefDnsCacheExpiration[] = "network.dnsCacheExpiration";
+static const char kPrefDnsCacheGrace[] = "network.dnsCacheExpirationGracePeriod";
+static const char kPrefIPv4OnlyDomains[] = "network.dns.ipv4OnlyDomains";
+static const char kPrefDisableIPv6[] = "network.dns.disableIPv6";
+static const char kPrefDisablePrefetch[] = "network.dns.disablePrefetch";
+static const char kPrefBlockDotOnion[] = "network.dns.blockDotOnion";
+static const char kPrefDnsLocalDomains[] = "network.dns.localDomains";
+static const char kPrefDnsOfflineLocalhost[] = "network.dns.offline-localhost";
+static const char kPrefDnsNotifyResolution[] = "network.dns.notifyResolution";
+
+//-----------------------------------------------------------------------------
+
+class nsDNSRecord : public nsIDNSRecord
+{
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIDNSRECORD
+
+ explicit nsDNSRecord(nsHostRecord *hostRecord)
+ : mHostRecord(hostRecord)
+ , mIter(nullptr)
+ , mIterGenCnt(-1)
+ , mDone(false) {}
+
+private:
+ virtual ~nsDNSRecord() = default;
+
+ RefPtr<nsHostRecord> mHostRecord;
+ NetAddrElement *mIter;
+ int mIterGenCnt; // the generation count of
+ // mHostRecord->addr_info when we
+ // start iterating
+ bool mDone;
+};
+
+NS_IMPL_ISUPPORTS(nsDNSRecord, nsIDNSRecord)
+
+NS_IMETHODIMP
+nsDNSRecord::GetCanonicalName(nsACString &result)
+{
+ // this method should only be called if we have a CNAME
+ NS_ENSURE_TRUE(mHostRecord->flags & nsHostResolver::RES_CANON_NAME,
+ NS_ERROR_NOT_AVAILABLE);
+
+ // if the record is for an IP address literal, then the canonical
+ // host name is the IP address literal.
+ const char *cname;
+ {
+ MutexAutoLock lock(mHostRecord->addr_info_lock);
+ if (mHostRecord->addr_info)
+ cname = mHostRecord->addr_info->mCanonicalName ?
+ mHostRecord->addr_info->mCanonicalName :
+ mHostRecord->addr_info->mHostName;
+ else
+ cname = mHostRecord->host;
+ result.Assign(cname);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSRecord::GetNextAddr(uint16_t port, NetAddr *addr)
+{
+ if (mDone) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ mHostRecord->addr_info_lock.Lock();
+ if (mHostRecord->addr_info) {
+ if (mIterGenCnt != mHostRecord->addr_info_gencnt) {
+ // mHostRecord->addr_info has changed, restart the iteration.
+ mIter = nullptr;
+ mIterGenCnt = mHostRecord->addr_info_gencnt;
+ }
+
+ bool startedFresh = !mIter;
+
+ do {
+ if (!mIter) {
+ mIter = mHostRecord->addr_info->mAddresses.getFirst();
+ } else {
+ mIter = mIter->getNext();
+ }
+ }
+ while (mIter && mHostRecord->Blacklisted(&mIter->mAddress));
+
+ if (!mIter && startedFresh) {
+ // If everything was blacklisted we want to reset the blacklist (and
+ // likely relearn it) and return the first address. That is better
+ // than nothing.
+ mHostRecord->ResetBlacklist();
+ mIter = mHostRecord->addr_info->mAddresses.getFirst();
+ }
+
+ if (mIter) {
+ memcpy(addr, &mIter->mAddress, sizeof(NetAddr));
+ }
+
+ mHostRecord->addr_info_lock.Unlock();
+
+ if (!mIter) {
+ mDone = true;
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ } else {
+ mHostRecord->addr_info_lock.Unlock();
+
+ if (!mHostRecord->addr) {
+ // Both mHostRecord->addr_info and mHostRecord->addr are null.
+ // This can happen if mHostRecord->addr_info expired and the
+ // attempt to reresolve it failed.
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ memcpy(addr, mHostRecord->addr, sizeof(NetAddr));
+ mDone = true;
+ }
+
+ // set given port
+ port = htons(port);
+ if (addr->raw.family == AF_INET) {
+ addr->inet.port = port;
+ } else if (addr->raw.family == AF_INET6) {
+ addr->inet6.port = port;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSRecord::GetAddresses(nsTArray<NetAddr> & aAddressArray)
+{
+ if (mDone) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ mHostRecord->addr_info_lock.Lock();
+ if (mHostRecord->addr_info) {
+ for (NetAddrElement *iter = mHostRecord->addr_info->mAddresses.getFirst();
+ iter; iter = iter->getNext()) {
+ if (mHostRecord->Blacklisted(&iter->mAddress)) {
+ continue;
+ }
+ NetAddr *addr = aAddressArray.AppendElement(NetAddr());
+ memcpy(addr, &iter->mAddress, sizeof(NetAddr));
+ if (addr->raw.family == AF_INET) {
+ addr->inet.port = 0;
+ } else if (addr->raw.family == AF_INET6) {
+ addr->inet6.port = 0;
+ }
+ }
+ mHostRecord->addr_info_lock.Unlock();
+ } else {
+ mHostRecord->addr_info_lock.Unlock();
+
+ if (!mHostRecord->addr) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+ NetAddr *addr = aAddressArray.AppendElement(NetAddr());
+ memcpy(addr, mHostRecord->addr, sizeof(NetAddr));
+ if (addr->raw.family == AF_INET) {
+ addr->inet.port = 0;
+ } else if (addr->raw.family == AF_INET6) {
+ addr->inet6.port = 0;
+ }
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSRecord::GetScriptableNextAddr(uint16_t port, nsINetAddr * *result)
+{
+ NetAddr addr;
+ nsresult rv = GetNextAddr(port, &addr);
+ if (NS_FAILED(rv)) return rv;
+
+ NS_ADDREF(*result = new nsNetAddr(&addr));
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSRecord::GetNextAddrAsString(nsACString &result)
+{
+ NetAddr addr;
+ nsresult rv = GetNextAddr(0, &addr);
+ if (NS_FAILED(rv)) return rv;
+
+ char buf[kIPv6CStrBufSize];
+ if (NetAddrToString(&addr, buf, sizeof(buf))) {
+ result.Assign(buf);
+ return NS_OK;
+ }
+ NS_ERROR("NetAddrToString failed unexpectedly");
+ return NS_ERROR_FAILURE; // conversion failed for some reason
+}
+
+NS_IMETHODIMP
+nsDNSRecord::HasMore(bool *result)
+{
+ if (mDone) {
+ *result = false;
+ return NS_OK;
+ }
+
+ NetAddrElement *iterCopy = mIter;
+ int iterGenCntCopy = mIterGenCnt;
+
+ NetAddr addr;
+ *result = NS_SUCCEEDED(GetNextAddr(0, &addr));
+
+ mIter = iterCopy;
+ mIterGenCnt = iterGenCntCopy;
+ mDone = false;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSRecord::Rewind()
+{
+ mIter = nullptr;
+ mIterGenCnt = -1;
+ mDone = false;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSRecord::ReportUnusable(uint16_t aPort)
+{
+ // right now we don't use the port in the blacklist
+
+ MutexAutoLock lock(mHostRecord->addr_info_lock);
+
+ // Check that we are using a real addr_info (as opposed to a single
+ // constant address), and that the generation count is valid. Otherwise,
+ // ignore the report.
+
+ if (mHostRecord->addr_info &&
+ mIterGenCnt == mHostRecord->addr_info_gencnt &&
+ mIter) {
+ mHostRecord->ReportUnusable(&mIter->mAddress);
+ }
+
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+
+class nsDNSAsyncRequest final : public nsResolveHostCallback
+ , public nsICancelable
+{
+ ~nsDNSAsyncRequest() = default;
+
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSICANCELABLE
+
+ nsDNSAsyncRequest(nsHostResolver *res,
+ const nsACString &host,
+ nsIDNSListener *listener,
+ uint16_t flags,
+ uint16_t af,
+ const nsACString &netInterface)
+ : mResolver(res)
+ , mHost(host)
+ , mListener(listener)
+ , mFlags(flags)
+ , mAF(af)
+ , mNetworkInterface(netInterface) {}
+
+ void OnLookupComplete(nsHostResolver *, nsHostRecord *, nsresult) override;
+ // Returns TRUE if the DNS listener arg is the same as the member listener
+ // Used in Cancellations to remove DNS requests associated with a
+ // particular hostname and nsIDNSListener
+ bool EqualsAsyncListener(nsIDNSListener *aListener) override;
+
+ size_t SizeOfIncludingThis(mozilla::MallocSizeOf) const override;
+
+ RefPtr<nsHostResolver> mResolver;
+ nsCString mHost; // hostname we're resolving
+ nsCOMPtr<nsIDNSListener> mListener;
+ uint16_t mFlags;
+ uint16_t mAF;
+ nsCString mNetworkInterface;
+};
+
+void
+nsDNSAsyncRequest::OnLookupComplete(nsHostResolver *resolver,
+ nsHostRecord *hostRecord,
+ nsresult status)
+{
+ // need to have an owning ref when we issue the callback to enable
+ // the caller to be able to addref/release multiple times without
+ // destroying the record prematurely.
+ nsCOMPtr<nsIDNSRecord> rec;
+ if (NS_SUCCEEDED(status)) {
+ NS_ASSERTION(hostRecord, "no host record");
+ rec = new nsDNSRecord(hostRecord);
+ }
+
+ mListener->OnLookupComplete(this, rec, status);
+ mListener = nullptr;
+
+ // release the reference to ourselves that was added before we were
+ // handed off to the host resolver.
+ NS_RELEASE_THIS();
+}
+
+bool
+nsDNSAsyncRequest::EqualsAsyncListener(nsIDNSListener *aListener)
+{
+ nsCOMPtr<nsIDNSListenerProxy> wrapper = do_QueryInterface(mListener);
+ if (wrapper) {
+ nsCOMPtr<nsIDNSListener> originalListener;
+ wrapper->GetOriginalListener(getter_AddRefs(originalListener));
+ return aListener == originalListener;
+ }
+ return (aListener == mListener);
+}
+
+size_t
+nsDNSAsyncRequest::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const
+{
+ size_t n = mallocSizeOf(this);
+
+ // The following fields aren't measured.
+ // - mHost, because it's a non-owning pointer
+ // - mResolver, because it's a non-owning pointer
+ // - mListener, because it's a non-owning pointer
+
+ return n;
+}
+
+NS_IMPL_ISUPPORTS(nsDNSAsyncRequest, nsICancelable)
+
+NS_IMETHODIMP
+nsDNSAsyncRequest::Cancel(nsresult reason)
+{
+ NS_ENSURE_ARG(NS_FAILED(reason));
+ mResolver->DetachCallback(mHost.get(), mFlags, mAF, mNetworkInterface.get(),
+ this, reason);
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+
+class nsDNSSyncRequest : public nsResolveHostCallback
+{
+public:
+ explicit nsDNSSyncRequest(PRMonitor *mon)
+ : mDone(false)
+ , mStatus(NS_OK)
+ , mMonitor(mon) {}
+ virtual ~nsDNSSyncRequest() = default;
+
+ void OnLookupComplete(nsHostResolver *, nsHostRecord *, nsresult) override;
+ bool EqualsAsyncListener(nsIDNSListener *aListener) override;
+ size_t SizeOfIncludingThis(mozilla::MallocSizeOf) const override;
+
+ bool mDone;
+ nsresult mStatus;
+ RefPtr<nsHostRecord> mHostRecord;
+
+private:
+ PRMonitor *mMonitor;
+};
+
+void
+nsDNSSyncRequest::OnLookupComplete(nsHostResolver *resolver,
+ nsHostRecord *hostRecord,
+ nsresult status)
+{
+ // store results, and wake up nsDNSService::Resolve to process results.
+ PR_EnterMonitor(mMonitor);
+ mDone = true;
+ mStatus = status;
+ mHostRecord = hostRecord;
+ PR_Notify(mMonitor);
+ PR_ExitMonitor(mMonitor);
+}
+
+bool
+nsDNSSyncRequest::EqualsAsyncListener(nsIDNSListener *aListener)
+{
+ // Sync request: no listener to compare
+ return false;
+}
+
+size_t
+nsDNSSyncRequest::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const
+{
+ size_t n = mallocSizeOf(this);
+
+ // The following fields aren't measured.
+ // - mHostRecord, because it's a non-owning pointer
+
+ // Measurement of the following members may be added later if DMD finds it
+ // is worthwhile:
+ // - mMonitor
+
+ return n;
+}
+
+class NotifyDNSResolution: public Runnable
+{
+public:
+ explicit NotifyDNSResolution(const nsACString &aHostname)
+ : mHostname(aHostname)
+ {
+ }
+
+ NS_IMETHOD Run() override
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+ nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
+ if (obs) {
+ obs->NotifyObservers(nullptr,
+ "dns-resolution-request",
+ NS_ConvertUTF8toUTF16(mHostname).get());
+ }
+ return NS_OK;
+ }
+
+private:
+ nsCString mHostname;
+};
+
+//-----------------------------------------------------------------------------
+
+nsDNSService::nsDNSService()
+ : mLock("nsDNSServer.mLock")
+ , mDisableIPv6(false)
+ , mDisablePrefetch(false)
+ , mFirstTime(true)
+ , mNotifyResolution(false)
+ , mOfflineLocalhost(false)
+{
+}
+
+nsDNSService::~nsDNSService() = default;
+
+NS_IMPL_ISUPPORTS(nsDNSService, nsIDNSService, nsPIDNSService, nsIObserver,
+ nsIMemoryReporter)
+
+/******************************************************************************
+ * nsDNSService impl:
+ * singleton instance ctor/dtor methods
+ ******************************************************************************/
+static nsDNSService *gDNSService;
+
+nsIDNSService*
+nsDNSService::GetXPCOMSingleton()
+{
+ if (IsNeckoChild()) {
+ return ChildDNSService::GetSingleton();
+ }
+
+ return GetSingleton();
+}
+
+nsDNSService*
+nsDNSService::GetSingleton()
+{
+ NS_ASSERTION(!IsNeckoChild(), "not a parent process");
+
+ if (gDNSService) {
+ NS_ADDREF(gDNSService);
+ return gDNSService;
+ }
+
+ gDNSService = new nsDNSService();
+ if (gDNSService) {
+ NS_ADDREF(gDNSService);
+ if (NS_FAILED(gDNSService->Init())) {
+ NS_RELEASE(gDNSService);
+ }
+ }
+
+ return gDNSService;
+}
+
+NS_IMETHODIMP
+nsDNSService::Init()
+{
+ if (mResolver)
+ return NS_OK;
+ NS_ENSURE_TRUE(!mResolver, NS_ERROR_ALREADY_INITIALIZED);
+ // prefs
+ uint32_t maxCacheEntries = 400;
+ uint32_t defaultCacheLifetime = 120; // seconds
+ uint32_t defaultGracePeriod = 60; // seconds
+ bool disableIPv6 = false;
+ bool offlineLocalhost = true;
+ bool disablePrefetch = false;
+ bool blockDotOnion = true;
+ int proxyType = nsIProtocolProxyService::PROXYCONFIG_DIRECT;
+ bool notifyResolution = false;
+
+ nsAdoptingCString ipv4OnlyDomains;
+ nsAdoptingCString localDomains;
+
+ // read prefs
+ nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
+ if (prefs) {
+ int32_t val;
+ if (NS_SUCCEEDED(prefs->GetIntPref(kPrefDnsCacheEntries, &val)))
+ maxCacheEntries = (uint32_t) val;
+ if (NS_SUCCEEDED(prefs->GetIntPref(kPrefDnsCacheExpiration, &val)))
+ defaultCacheLifetime = val;
+ if (NS_SUCCEEDED(prefs->GetIntPref(kPrefDnsCacheGrace, &val)))
+ defaultGracePeriod = val;
+
+ // ASSUMPTION: pref branch does not modify out params on failure
+ prefs->GetBoolPref(kPrefDisableIPv6, &disableIPv6);
+ prefs->GetCharPref(kPrefIPv4OnlyDomains, getter_Copies(ipv4OnlyDomains));
+ prefs->GetCharPref(kPrefDnsLocalDomains, getter_Copies(localDomains));
+ prefs->GetBoolPref(kPrefDnsOfflineLocalhost, &offlineLocalhost);
+ prefs->GetBoolPref(kPrefDisablePrefetch, &disablePrefetch);
+ prefs->GetBoolPref(kPrefBlockDotOnion, &blockDotOnion);
+
+ // If a manual proxy is in use, disable prefetch implicitly
+ prefs->GetIntPref("network.proxy.type", &proxyType);
+ prefs->GetBoolPref(kPrefDnsNotifyResolution, &notifyResolution);
+
+ if (mFirstTime) {
+ mFirstTime = false;
+
+ // register as prefs observer
+ prefs->AddObserver(kPrefDnsCacheEntries, this, false);
+ prefs->AddObserver(kPrefDnsCacheExpiration, this, false);
+ prefs->AddObserver(kPrefDnsCacheGrace, this, false);
+ prefs->AddObserver(kPrefIPv4OnlyDomains, this, false);
+ prefs->AddObserver(kPrefDnsLocalDomains, this, false);
+ prefs->AddObserver(kPrefDisableIPv6, this, false);
+ prefs->AddObserver(kPrefDnsOfflineLocalhost, this, false);
+ prefs->AddObserver(kPrefDisablePrefetch, this, false);
+ prefs->AddObserver(kPrefBlockDotOnion, this, false);
+ prefs->AddObserver(kPrefDnsNotifyResolution, this, false);
+
+ // Monitor these to see if there is a change in proxy configuration
+ // If a manual proxy is in use, disable prefetch implicitly
+ prefs->AddObserver("network.proxy.type", this, false);
+ }
+ }
+
+ nsCOMPtr<nsIObserverService> observerService =
+ mozilla::services::GetObserverService();
+ if (observerService) {
+ observerService->AddObserver(this, "last-pb-context-exited", false);
+ observerService->AddObserver(this, NS_NETWORK_LINK_TOPIC, false);
+ }
+
+ nsDNSPrefetch::Initialize(this);
+
+ nsCOMPtr<nsIIDNService> idn = do_GetService(NS_IDNSERVICE_CONTRACTID);
+
+ RefPtr<nsHostResolver> res;
+ nsresult rv = nsHostResolver::Create(maxCacheEntries,
+ defaultCacheLifetime,
+ defaultGracePeriod,
+ getter_AddRefs(res));
+ if (NS_SUCCEEDED(rv)) {
+ // now, set all of our member variables while holding the lock
+ MutexAutoLock lock(mLock);
+ mResolver = res;
+ mIDN = idn;
+ mIPv4OnlyDomains = ipv4OnlyDomains; // exchanges buffer ownership
+ mOfflineLocalhost = offlineLocalhost;
+ mDisableIPv6 = disableIPv6;
+ mBlockDotOnion = blockDotOnion;
+
+ // Disable prefetching either by explicit preference or if a manual proxy is configured
+ mDisablePrefetch = disablePrefetch || (proxyType == nsIProtocolProxyService::PROXYCONFIG_MANUAL);
+
+ mLocalDomains.Clear();
+ if (localDomains) {
+ nsCCharSeparatedTokenizer tokenizer(localDomains, ',',
+ nsCCharSeparatedTokenizer::SEPARATOR_OPTIONAL);
+
+ while (tokenizer.hasMoreTokens()) {
+ mLocalDomains.PutEntry(tokenizer.nextToken());
+ }
+ }
+ mNotifyResolution = notifyResolution;
+ }
+
+ RegisterWeakMemoryReporter(this);
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsDNSService::Shutdown()
+{
+ UnregisterWeakMemoryReporter(this);
+
+ RefPtr<nsHostResolver> res;
+ {
+ MutexAutoLock lock(mLock);
+ res = mResolver;
+ mResolver = nullptr;
+ }
+ if (res) {
+ res->Shutdown();
+ }
+
+ nsCOMPtr<nsIObserverService> observerService =
+ mozilla::services::GetObserverService();
+ if (observerService) {
+ observerService->RemoveObserver(this, NS_NETWORK_LINK_TOPIC);
+ observerService->RemoveObserver(this, "last-pb-context-exited");
+ }
+
+ return NS_OK;
+}
+
+bool
+nsDNSService::GetOffline() const
+{
+ bool offline = false;
+ nsCOMPtr<nsIIOService> io = do_GetService(NS_IOSERVICE_CONTRACTID);
+ if (io) {
+ io->GetOffline(&offline);
+ }
+ return offline;
+}
+
+NS_IMETHODIMP
+nsDNSService::GetPrefetchEnabled(bool *outVal)
+{
+ MutexAutoLock lock(mLock);
+ *outVal = !mDisablePrefetch;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSService::SetPrefetchEnabled(bool inVal)
+{
+ MutexAutoLock lock(mLock);
+ mDisablePrefetch = !inVal;
+ return NS_OK;
+}
+
+nsresult
+nsDNSService::PreprocessHostname(bool aLocalDomain,
+ const nsACString &aInput,
+ nsIIDNService *aIDN,
+ nsACString &aACE)
+{
+ // Enforce RFC 7686
+ if (mBlockDotOnion &&
+ StringEndsWith(aInput, NS_LITERAL_CSTRING(".onion"))) {
+ return NS_ERROR_UNKNOWN_HOST;
+ }
+
+ if (aLocalDomain) {
+ aACE.AssignLiteral("localhost");
+ return NS_OK;
+ }
+
+ if (!aIDN || IsASCII(aInput)) {
+ aACE = aInput;
+ return NS_OK;
+ }
+
+ if (!(IsUTF8(aInput) && NS_SUCCEEDED(aIDN->ConvertUTF8toACE(aInput, aACE)))) {
+ return NS_ERROR_FAILURE;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSService::AsyncResolve(const nsACString &aHostname,
+ uint32_t flags,
+ nsIDNSListener *listener,
+ nsIEventTarget *target_,
+ nsICancelable **result)
+{
+ return AsyncResolveExtended(aHostname, flags, EmptyCString(), listener, target_,
+ result);
+}
+
+NS_IMETHODIMP
+nsDNSService::AsyncResolveExtended(const nsACString &aHostname,
+ uint32_t flags,
+ const nsACString &aNetworkInterface,
+ nsIDNSListener *listener,
+ nsIEventTarget *target_,
+ nsICancelable **result)
+{
+ // grab reference to global host resolver and IDN service. beware
+ // simultaneous shutdown!!
+ RefPtr<nsHostResolver> res;
+ nsCOMPtr<nsIIDNService> idn;
+ nsCOMPtr<nsIEventTarget> target = target_;
+ bool localDomain = false;
+ {
+ MutexAutoLock lock(mLock);
+
+ if (mDisablePrefetch && (flags & RESOLVE_SPECULATE))
+ return NS_ERROR_DNS_LOOKUP_QUEUE_FULL;
+
+ res = mResolver;
+ idn = mIDN;
+ localDomain = mLocalDomains.GetEntry(aHostname);
+ }
+
+ if (mNotifyResolution) {
+ NS_DispatchToMainThread(new NotifyDNSResolution(aHostname));
+ }
+
+ if (!res)
+ return NS_ERROR_OFFLINE;
+
+ nsCString hostname;
+ nsresult rv = PreprocessHostname(localDomain, aHostname, idn, hostname);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ if (GetOffline() &&
+ (!mOfflineLocalhost || !hostname.LowerCaseEqualsASCII("localhost"))) {
+ flags |= RESOLVE_OFFLINE;
+ }
+
+ // make sure JS callers get notification on the main thread
+ nsCOMPtr<nsIXPConnectWrappedJS> wrappedListener = do_QueryInterface(listener);
+ if (wrappedListener && !target) {
+ nsCOMPtr<nsIThread> mainThread;
+ NS_GetMainThread(getter_AddRefs(mainThread));
+ target = do_QueryInterface(mainThread);
+ }
+
+ if (target) {
+ listener = new DNSListenerProxy(listener, target);
+ }
+
+ uint16_t af = GetAFForLookup(hostname, flags);
+
+ auto *req =
+ new nsDNSAsyncRequest(res, hostname, listener, flags, af,
+ aNetworkInterface);
+ if (!req)
+ return NS_ERROR_OUT_OF_MEMORY;
+ NS_ADDREF(*result = req);
+
+ // addref for resolver; will be released when OnLookupComplete is called.
+ NS_ADDREF(req);
+ rv = res->ResolveHost(req->mHost.get(), flags, af,
+ req->mNetworkInterface.get(), req);
+ if (NS_FAILED(rv)) {
+ NS_RELEASE(req);
+ NS_RELEASE(*result);
+ }
+ return rv;
+}
+
+NS_IMETHODIMP
+nsDNSService::CancelAsyncResolve(const nsACString &aHostname,
+ uint32_t aFlags,
+ nsIDNSListener *aListener,
+ nsresult aReason)
+{
+ return CancelAsyncResolveExtended(aHostname, aFlags, EmptyCString(), aListener,
+ aReason);
+}
+
+NS_IMETHODIMP
+nsDNSService::CancelAsyncResolveExtended(const nsACString &aHostname,
+ uint32_t aFlags,
+ const nsACString &aNetworkInterface,
+ nsIDNSListener *aListener,
+ nsresult aReason)
+{
+ // grab reference to global host resolver and IDN service. beware
+ // simultaneous shutdown!!
+ RefPtr<nsHostResolver> res;
+ nsCOMPtr<nsIIDNService> idn;
+ bool localDomain = false;
+ {
+ MutexAutoLock lock(mLock);
+
+ if (mDisablePrefetch && (aFlags & RESOLVE_SPECULATE))
+ return NS_ERROR_DNS_LOOKUP_QUEUE_FULL;
+
+ res = mResolver;
+ idn = mIDN;
+ localDomain = mLocalDomains.GetEntry(aHostname);
+ }
+ if (!res)
+ return NS_ERROR_OFFLINE;
+
+ nsCString hostname;
+ nsresult rv = PreprocessHostname(localDomain, aHostname, idn, hostname);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ uint16_t af = GetAFForLookup(hostname, aFlags);
+
+ res->CancelAsyncRequest(hostname.get(), aFlags, af,
+ nsPromiseFlatCString(aNetworkInterface).get(), aListener,
+ aReason);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDNSService::Resolve(const nsACString &aHostname,
+ uint32_t flags,
+ nsIDNSRecord **result)
+{
+ // grab reference to global host resolver and IDN service. beware
+ // simultaneous shutdown!!
+ RefPtr<nsHostResolver> res;
+ nsCOMPtr<nsIIDNService> idn;
+ bool localDomain = false;
+ {
+ MutexAutoLock lock(mLock);
+ res = mResolver;
+ idn = mIDN;
+ localDomain = mLocalDomains.GetEntry(aHostname);
+ }
+
+ if (mNotifyResolution) {
+ NS_DispatchToMainThread(new NotifyDNSResolution(aHostname));
+ }
+
+ NS_ENSURE_TRUE(res, NS_ERROR_OFFLINE);
+
+ nsCString hostname;
+ nsresult rv = PreprocessHostname(localDomain, aHostname, idn, hostname);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ if (GetOffline() &&
+ (!mOfflineLocalhost || !hostname.LowerCaseEqualsASCII("localhost"))) {
+ flags |= RESOLVE_OFFLINE;
+ }
+
+ //
+ // sync resolve: since the host resolver only works asynchronously, we need
+ // to use a mutex and a condvar to wait for the result. however, since the
+ // result may be in the resolvers cache, we might get called back recursively
+ // on the same thread. so, our mutex needs to be re-entrant. in other words,
+ // we need to use a monitor! ;-)
+ //
+
+ PRMonitor *mon = PR_NewMonitor();
+ if (!mon)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ PR_EnterMonitor(mon);
+ nsDNSSyncRequest syncReq(mon);
+
+ uint16_t af = GetAFForLookup(hostname, flags);
+
+ rv = res->ResolveHost(hostname.get(), flags, af, "", &syncReq);
+ if (NS_SUCCEEDED(rv)) {
+ // wait for result
+ while (!syncReq.mDone)
+ PR_Wait(mon, PR_INTERVAL_NO_TIMEOUT);
+
+ if (NS_FAILED(syncReq.mStatus))
+ rv = syncReq.mStatus;
+ else {
+ NS_ASSERTION(syncReq.mHostRecord, "no host record");
+ auto *rec = new nsDNSRecord(syncReq.mHostRecord);
+ if (!rec)
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ else
+ NS_ADDREF(*result = rec);
+ }
+ }
+
+ PR_ExitMonitor(mon);
+ PR_DestroyMonitor(mon);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsDNSService::GetMyHostName(nsACString &result)
+{
+ char name[100];
+ if (PR_GetSystemInfo(PR_SI_HOSTNAME, name, sizeof(name)) == PR_SUCCESS) {
+ result = name;
+ return NS_OK;
+ }
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsDNSService::Observe(nsISupports *subject, const char *topic, const char16_t *data)
+{
+ // We are only getting called if a preference has changed or there's a
+ // network link event.
+ NS_ASSERTION(strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0 ||
+ strcmp(topic, "last-pb-context-exited") == 0 ||
+ strcmp(topic, NS_NETWORK_LINK_TOPIC) == 0,
+ "unexpected observe call");
+
+ bool flushCache = false;
+ if (!strcmp(topic, NS_NETWORK_LINK_TOPIC)) {
+ nsAutoCString converted = NS_ConvertUTF16toUTF8(data);
+ if (mResolver && !strcmp(converted.get(), NS_NETWORK_LINK_DATA_CHANGED)) {
+ flushCache = true;
+ }
+ } else if (!strcmp(topic, "last-pb-context-exited")) {
+ flushCache = true;
+ }
+ if (flushCache) {
+ mResolver->FlushCache();
+ return NS_OK;
+ }
+
+ //
+ // Shutdown and this function are both only called on the UI thread, so we don't
+ // have to worry about mResolver being cleared out from under us.
+ //
+ // NOTE Shutting down and reinitializing the service like this is obviously
+ // suboptimal if Observe gets called several times in a row, but we don't
+ // expect that to be the case.
+ //
+
+ if (mResolver) {
+ Shutdown();
+ }
+ Init();
+ return NS_OK;
+}
+
+uint16_t
+nsDNSService::GetAFForLookup(const nsACString &host, uint32_t flags)
+{
+ if (mDisableIPv6 || (flags & RESOLVE_DISABLE_IPV6))
+ return PR_AF_INET;
+
+ MutexAutoLock lock(mLock);
+
+ uint16_t af = PR_AF_UNSPEC;
+
+ if (!mIPv4OnlyDomains.IsEmpty()) {
+ const char *domain, *domainEnd, *end;
+ uint32_t hostLen, domainLen;
+
+ // see if host is in one of the IPv4-only domains
+ domain = mIPv4OnlyDomains.BeginReading();
+ domainEnd = mIPv4OnlyDomains.EndReading();
+
+ nsACString::const_iterator hostStart;
+ host.BeginReading(hostStart);
+ hostLen = host.Length();
+
+ do {
+ // skip any whitespace
+ while (*domain == ' ' || *domain == '\t')
+ ++domain;
+
+ // find end of this domain in the string
+ end = strchr(domain, ',');
+ if (!end)
+ end = domainEnd;
+
+ // to see if the hostname is in the domain, check if the domain
+ // matches the end of the hostname.
+ domainLen = end - domain;
+ if (domainLen && hostLen >= domainLen) {
+ const char *hostTail = hostStart.get() + hostLen - domainLen;
+ if (PL_strncasecmp(domain, hostTail, domainLen) == 0) {
+ // now, make sure either that the hostname is a direct match or
+ // that the hostname begins with a dot.
+ if (hostLen == domainLen ||
+ *hostTail == '.' || *(hostTail - 1) == '.') {
+ af = PR_AF_INET;
+ break;
+ }
+ }
+ }
+
+ domain = end + 1;
+ } while (*end);
+ }
+
+ if ((af != PR_AF_INET) && (flags & RESOLVE_DISABLE_IPV4))
+ af = PR_AF_INET6;
+
+ return af;
+}
+
+NS_IMETHODIMP
+nsDNSService::GetDNSCacheEntries(nsTArray<mozilla::net::DNSCacheEntries> *args)
+{
+ NS_ENSURE_TRUE(mResolver, NS_ERROR_NOT_INITIALIZED);
+ mResolver->GetDNSCacheEntries(args);
+ return NS_OK;
+}
+
+size_t
+nsDNSService::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
+{
+ // Measurement of the following members may be added later if DMD finds it
+ // is worthwhile:
+ // - mIDN
+ // - mLock
+
+ size_t n = mallocSizeOf(this);
+ n += mResolver ? mResolver->SizeOfIncludingThis(mallocSizeOf) : 0;
+ n += mIPv4OnlyDomains.SizeOfExcludingThisIfUnshared(mallocSizeOf);
+ n += mLocalDomains.SizeOfExcludingThis(mallocSizeOf);
+ return n;
+}
+
+MOZ_DEFINE_MALLOC_SIZE_OF(DNSServiceMallocSizeOf)
+
+NS_IMETHODIMP
+nsDNSService::CollectReports(nsIHandleReportCallback* aHandleReport,
+ nsISupports* aData, bool aAnonymize)
+{
+ MOZ_COLLECT_REPORT(
+ "explicit/network/dns-service", KIND_HEAP, UNITS_BYTES,
+ SizeOfIncludingThis(DNSServiceMallocSizeOf),
+ "Memory used for the DNS service.");
+
+ return NS_OK;
+}
+
diff --git a/netwerk/dns/nsDNSService2.h b/netwerk/dns/nsDNSService2.h
new file mode 100644
index 000000000..79454b901
--- /dev/null
+++ b/netwerk/dns/nsDNSService2.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set sw=4 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsDNSService2_h__
+#define nsDNSService2_h__
+
+#include "nsPIDNSService.h"
+#include "nsIIDNService.h"
+#include "nsIMemoryReporter.h"
+#include "nsIObserver.h"
+#include "nsHostResolver.h"
+#include "nsAutoPtr.h"
+#include "nsString.h"
+#include "nsTHashtable.h"
+#include "nsHashKeys.h"
+#include "mozilla/Mutex.h"
+#include "mozilla/Attributes.h"
+
+class nsDNSService final : public nsPIDNSService
+ , public nsIObserver
+ , public nsIMemoryReporter
+{
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSPIDNSSERVICE
+ NS_DECL_NSIDNSSERVICE
+ NS_DECL_NSIOBSERVER
+ NS_DECL_NSIMEMORYREPORTER
+
+ nsDNSService();
+
+ static nsIDNSService* GetXPCOMSingleton();
+
+ size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
+
+ bool GetOffline() const;
+
+private:
+ ~nsDNSService();
+
+ static nsDNSService* GetSingleton();
+
+ uint16_t GetAFForLookup(const nsACString &host, uint32_t flags);
+
+ nsresult PreprocessHostname(bool aLocalDomain,
+ const nsACString &aInput,
+ nsIIDNService *aIDN,
+ nsACString &aACE);
+
+ RefPtr<nsHostResolver> mResolver;
+ nsCOMPtr<nsIIDNService> mIDN;
+
+ // mLock protects access to mResolver and mIPv4OnlyDomains
+ mozilla::Mutex mLock;
+
+ // mIPv4OnlyDomains is a comma-separated list of domains for which only
+ // IPv4 DNS lookups are performed. This allows the user to disable IPv6 on
+ // a per-domain basis and work around broken DNS servers. See bug 68796.
+ nsAdoptingCString mIPv4OnlyDomains;
+ bool mDisableIPv6;
+ bool mDisablePrefetch;
+ bool mBlockDotOnion;
+ bool mFirstTime;
+ bool mNotifyResolution;
+ bool mOfflineLocalhost;
+ nsTHashtable<nsCStringHashKey> mLocalDomains;
+};
+
+#endif //nsDNSService2_h__
diff --git a/netwerk/dns/nsEffectiveTLDService.cpp b/netwerk/dns/nsEffectiveTLDService.cpp
new file mode 100644
index 000000000..4dab2178f
--- /dev/null
+++ b/netwerk/dns/nsEffectiveTLDService.cpp
@@ -0,0 +1,368 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// This service reads a file of rules describing TLD-like domain names. For a
+// complete description of the expected file format and parsing rules, see
+// http://wiki.mozilla.org/Gecko:Effective_TLD_Service
+
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/MemoryReporting.h"
+
+#include "nsEffectiveTLDService.h"
+#include "nsIIDNService.h"
+#include "nsNetUtil.h"
+#include "prnetdb.h"
+#include "nsIURI.h"
+#include "nsNetCID.h"
+#include "nsServiceManagerUtils.h"
+
+using namespace mozilla;
+
+NS_IMPL_ISUPPORTS(nsEffectiveTLDService, nsIEffectiveTLDService,
+ nsIMemoryReporter)
+
+// ----------------------------------------------------------------------
+
+#define ETLD_STR_NUM_1(line) str##line
+#define ETLD_STR_NUM(line) ETLD_STR_NUM_1(line)
+#define ETLD_ENTRY_OFFSET(name) offsetof(struct etld_string_list, ETLD_STR_NUM(__LINE__))
+
+const ETLDEntry ETLDEntry::entries[] = {
+#define ETLD_ENTRY(name, ex, wild) { ETLD_ENTRY_OFFSET(name), ex, wild },
+#include "etld_data.inc"
+#undef ETLD_ENTRY
+};
+
+const union ETLDEntry::etld_strings ETLDEntry::strings = {
+ {
+#define ETLD_ENTRY(name, ex, wild) name,
+#include "etld_data.inc"
+#undef ETLD_ENTRY
+ }
+};
+
+/* static */ const ETLDEntry*
+ETLDEntry::GetEntry(const char* aDomain)
+{
+ size_t i;
+ if (BinarySearchIf(entries, 0, ArrayLength(ETLDEntry::entries),
+ Cmp(aDomain), &i)) {
+ return &entries[i];
+ }
+ return nullptr;
+}
+
+// Dummy function to statically ensure that our indices don't overflow
+// the storage provided for them.
+void
+ETLDEntry::FuncForStaticAsserts(void)
+{
+#define ETLD_ENTRY(name, ex, wild) \
+ static_assert(ETLD_ENTRY_OFFSET(name) < (1 << ETLD_ENTRY_N_INDEX_BITS), \
+ "invalid strtab index");
+#include "etld_data.inc"
+#undef ETLD_ENTRY
+}
+
+#undef ETLD_ENTRY_OFFSET
+#undef ETLD_STR_NUM
+#undef ETLD_STR_NUM1
+
+// ----------------------------------------------------------------------
+
+static nsEffectiveTLDService *gService = nullptr;
+
+nsEffectiveTLDService::nsEffectiveTLDService()
+{
+}
+
+nsresult
+nsEffectiveTLDService::Init()
+{
+ nsresult rv;
+ mIDNService = do_GetService(NS_IDNSERVICE_CONTRACTID, &rv);
+ if (NS_FAILED(rv)) return rv;
+
+#ifdef DEBUG
+ // Sanity-check the eTLD entries.
+ for (uint32_t i = 0; i < ArrayLength(ETLDEntry::entries); i++) {
+ const char* domain = ETLDEntry::entries[i].GetEffectiveTLDName();
+ nsDependentCString name(domain);
+ nsAutoCString normalizedName(domain);
+ MOZ_ASSERT(NS_SUCCEEDED(NormalizeHostname(normalizedName)),
+ "normalization failure!");
+ MOZ_ASSERT(name.Equals(normalizedName), "domain not normalized!");
+
+ // Domains must be in sorted order for binary search to work.
+ if (i > 0) {
+ const char* domain0 = ETLDEntry::entries[i - 1].GetEffectiveTLDName();
+ MOZ_ASSERT(strcmp(domain0, domain) < 0, "domains not in sorted order!");
+ }
+ }
+#endif
+
+ MOZ_ASSERT(!gService);
+ gService = this;
+ RegisterWeakMemoryReporter(this);
+
+ return NS_OK;
+}
+
+nsEffectiveTLDService::~nsEffectiveTLDService()
+{
+ UnregisterWeakMemoryReporter(this);
+ gService = nullptr;
+}
+
+MOZ_DEFINE_MALLOC_SIZE_OF(EffectiveTLDServiceMallocSizeOf)
+
+// The amount of heap memory measured here is tiny. It used to be bigger when
+// nsEffectiveTLDService used a separate hash table instead of binary search.
+// Nonetheless, we keep this code here in anticipation of bug 1083971 which will
+// change ETLDEntries::entries to a heap-allocated array modifiable at runtime.
+NS_IMETHODIMP
+nsEffectiveTLDService::CollectReports(nsIHandleReportCallback* aHandleReport,
+ nsISupports* aData, bool aAnonymize)
+{
+ MOZ_COLLECT_REPORT(
+ "explicit/network/effective-TLD-service", KIND_HEAP, UNITS_BYTES,
+ SizeOfIncludingThis(EffectiveTLDServiceMallocSizeOf),
+ "Memory used by the effective TLD service.");
+
+ return NS_OK;
+}
+
+size_t
+nsEffectiveTLDService::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
+{
+ size_t n = aMallocSizeOf(this);
+
+ // Measurement of the following members may be added later if DMD finds it is
+ // worthwhile:
+ // - mIDNService
+
+ return n;
+}
+
+// External function for dealing with URI's correctly.
+// Pulls out the host portion from an nsIURI, and calls through to
+// GetPublicSuffixFromHost().
+NS_IMETHODIMP
+nsEffectiveTLDService::GetPublicSuffix(nsIURI *aURI,
+ nsACString &aPublicSuffix)
+{
+ NS_ENSURE_ARG_POINTER(aURI);
+
+ nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(aURI);
+ NS_ENSURE_ARG_POINTER(innerURI);
+
+ nsAutoCString host;
+ nsresult rv = innerURI->GetAsciiHost(host);
+ if (NS_FAILED(rv)) return rv;
+
+ return GetBaseDomainInternal(host, 0, aPublicSuffix);
+}
+
+// External function for dealing with URI's correctly.
+// Pulls out the host portion from an nsIURI, and calls through to
+// GetBaseDomainFromHost().
+NS_IMETHODIMP
+nsEffectiveTLDService::GetBaseDomain(nsIURI *aURI,
+ uint32_t aAdditionalParts,
+ nsACString &aBaseDomain)
+{
+ NS_ENSURE_ARG_POINTER(aURI);
+ NS_ENSURE_TRUE( ((int32_t)aAdditionalParts) >= 0, NS_ERROR_INVALID_ARG);
+
+ nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(aURI);
+ NS_ENSURE_ARG_POINTER(innerURI);
+
+ nsAutoCString host;
+ nsresult rv = innerURI->GetAsciiHost(host);
+ if (NS_FAILED(rv)) return rv;
+
+ return GetBaseDomainInternal(host, aAdditionalParts + 1, aBaseDomain);
+}
+
+// External function for dealing with a host string directly: finds the public
+// suffix (e.g. co.uk) for the given hostname. See GetBaseDomainInternal().
+NS_IMETHODIMP
+nsEffectiveTLDService::GetPublicSuffixFromHost(const nsACString &aHostname,
+ nsACString &aPublicSuffix)
+{
+ // Create a mutable copy of the hostname and normalize it to ACE.
+ // This will fail if the hostname includes invalid characters.
+ nsAutoCString normHostname(aHostname);
+ nsresult rv = NormalizeHostname(normHostname);
+ if (NS_FAILED(rv)) return rv;
+
+ return GetBaseDomainInternal(normHostname, 0, aPublicSuffix);
+}
+
+// External function for dealing with a host string directly: finds the base
+// domain (e.g. www.co.uk) for the given hostname and number of subdomain parts
+// requested. See GetBaseDomainInternal().
+NS_IMETHODIMP
+nsEffectiveTLDService::GetBaseDomainFromHost(const nsACString &aHostname,
+ uint32_t aAdditionalParts,
+ nsACString &aBaseDomain)
+{
+ NS_ENSURE_TRUE( ((int32_t)aAdditionalParts) >= 0, NS_ERROR_INVALID_ARG);
+
+ // Create a mutable copy of the hostname and normalize it to ACE.
+ // This will fail if the hostname includes invalid characters.
+ nsAutoCString normHostname(aHostname);
+ nsresult rv = NormalizeHostname(normHostname);
+ if (NS_FAILED(rv)) return rv;
+
+ return GetBaseDomainInternal(normHostname, aAdditionalParts + 1, aBaseDomain);
+}
+
+NS_IMETHODIMP
+nsEffectiveTLDService::GetNextSubDomain(const nsACString& aHostname,
+ nsACString& aBaseDomain)
+{
+ // Create a mutable copy of the hostname and normalize it to ACE.
+ // This will fail if the hostname includes invalid characters.
+ nsAutoCString normHostname(aHostname);
+ nsresult rv = NormalizeHostname(normHostname);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return GetBaseDomainInternal(normHostname, -1, aBaseDomain);
+}
+
+// Finds the base domain for a host, with requested number of additional parts.
+// This will fail, generating an error, if the host is an IPv4/IPv6 address,
+// if more subdomain parts are requested than are available, or if the hostname
+// includes characters that are not valid in a URL. Normalization is performed
+// on the host string and the result will be in UTF8.
+nsresult
+nsEffectiveTLDService::GetBaseDomainInternal(nsCString &aHostname,
+ int32_t aAdditionalParts,
+ nsACString &aBaseDomain)
+{
+ if (aHostname.IsEmpty())
+ return NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS;
+
+ // chomp any trailing dot, and keep track of it for later
+ bool trailingDot = aHostname.Last() == '.';
+ if (trailingDot)
+ aHostname.Truncate(aHostname.Length() - 1);
+
+ // check the edge cases of the host being '.' or having a second trailing '.',
+ // since subsequent checks won't catch it.
+ if (aHostname.IsEmpty() || aHostname.Last() == '.')
+ return NS_ERROR_INVALID_ARG;
+
+ // Check if we're dealing with an IPv4/IPv6 hostname, and return
+ PRNetAddr addr;
+ PRStatus result = PR_StringToNetAddr(aHostname.get(), &addr);
+ if (result == PR_SUCCESS)
+ return NS_ERROR_HOST_IS_IP_ADDRESS;
+
+ // Walk up the domain tree, most specific to least specific,
+ // looking for matches at each level. Note that a given level may
+ // have multiple attributes (e.g. IsWild() and IsNormal()).
+ const char *prevDomain = nullptr;
+ const char *currDomain = aHostname.get();
+ const char *nextDot = strchr(currDomain, '.');
+ const char *end = currDomain + aHostname.Length();
+ // Default value of *eTLD is currDomain as set in the while loop below
+ const char *eTLD = nullptr;
+ while (true) {
+ // sanity check the string we're about to look up: it should not begin with
+ // a '.'; this would mean the hostname began with a '.' or had an
+ // embedded '..' sequence.
+ if (*currDomain == '.')
+ return NS_ERROR_INVALID_ARG;
+
+ // Perform the lookup.
+ const ETLDEntry* entry = ETLDEntry::GetEntry(currDomain);
+ if (entry) {
+ if (entry->IsWild() && prevDomain) {
+ // wildcard rules imply an eTLD one level inferior to the match.
+ eTLD = prevDomain;
+ break;
+
+ } else if (entry->IsNormal() || !nextDot) {
+ // specific match, or we've hit the top domain level
+ eTLD = currDomain;
+ break;
+
+ } else if (entry->IsException()) {
+ // exception rules imply an eTLD one level superior to the match.
+ eTLD = nextDot + 1;
+ break;
+ }
+ }
+
+ if (!nextDot) {
+ // we've hit the top domain level; use it by default.
+ eTLD = currDomain;
+ break;
+ }
+
+ prevDomain = currDomain;
+ currDomain = nextDot + 1;
+ nextDot = strchr(currDomain, '.');
+ }
+
+ const char *begin, *iter;
+ if (aAdditionalParts < 0) {
+ NS_ASSERTION(aAdditionalParts == -1,
+ "aAdditionalParts can't be negative and different from -1");
+
+ for (iter = aHostname.get(); iter != eTLD && *iter != '.'; iter++);
+
+ if (iter != eTLD) {
+ iter++;
+ }
+ if (iter != eTLD) {
+ aAdditionalParts = 0;
+ }
+ } else {
+ // count off the number of requested domains.
+ begin = aHostname.get();
+ iter = eTLD;
+
+ while (true) {
+ if (iter == begin)
+ break;
+
+ if (*(--iter) == '.' && aAdditionalParts-- == 0) {
+ ++iter;
+ ++aAdditionalParts;
+ break;
+ }
+ }
+ }
+
+ if (aAdditionalParts != 0)
+ return NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS;
+
+ aBaseDomain = Substring(iter, end);
+ // add on the trailing dot, if applicable
+ if (trailingDot)
+ aBaseDomain.Append('.');
+
+ return NS_OK;
+}
+
+// Normalizes the given hostname, component by component. ASCII/ACE
+// components are lower-cased, and UTF-8 components are normalized per
+// RFC 3454 and converted to ACE.
+nsresult
+nsEffectiveTLDService::NormalizeHostname(nsCString &aHostname)
+{
+ if (!IsASCII(aHostname)) {
+ nsresult rv = mIDNService->ConvertUTF8toACE(aHostname, aHostname);
+ if (NS_FAILED(rv))
+ return rv;
+ }
+
+ ToLowerCase(aHostname);
+ return NS_OK;
+}
diff --git a/netwerk/dns/nsEffectiveTLDService.h b/netwerk/dns/nsEffectiveTLDService.h
new file mode 100644
index 000000000..92e7abe05
--- /dev/null
+++ b/netwerk/dns/nsEffectiveTLDService.h
@@ -0,0 +1,98 @@
+//* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef EffectiveTLDService_h
+#define EffectiveTLDService_h
+
+#include "nsIEffectiveTLDService.h"
+
+#include "nsIMemoryReporter.h"
+#include "nsString.h"
+#include "nsCOMPtr.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/BinarySearch.h"
+#include "mozilla/MemoryReporting.h"
+
+class nsIIDNService;
+
+// struct for static data generated from effective_tld_names.dat
+struct ETLDEntry {
+ friend class nsEffectiveTLDService;
+
+public:
+ bool IsNormal() const { return wild || !exception; }
+ bool IsException() const { return exception; }
+ bool IsWild() const { return wild; }
+
+ const char* GetEffectiveTLDName() const
+ {
+ return strings.strtab + strtab_index;
+ }
+
+ static const ETLDEntry* GetEntry(const char* aDomain);
+
+ static const size_t ETLD_ENTRY_N_INDEX_BITS = 30;
+
+ // These fields must be public to allow static construction.
+ uint32_t strtab_index : ETLD_ENTRY_N_INDEX_BITS;
+ uint32_t exception : 1;
+ uint32_t wild : 1;
+
+private:
+ struct Cmp {
+ int operator()(const ETLDEntry aEntry) const
+ {
+ return strcmp(mName, aEntry.GetEffectiveTLDName());
+ }
+ explicit Cmp(const char* aName) : mName(aName) {}
+ const char* mName;
+ };
+
+#define ETLD_STR_NUM_1(line) str##line
+#define ETLD_STR_NUM(line) ETLD_STR_NUM_1(line)
+ struct etld_string_list {
+#define ETLD_ENTRY(name, ex, wild) char ETLD_STR_NUM(__LINE__)[sizeof(name)];
+#include "etld_data.inc"
+#undef ETLD_ENTRY
+ };
+
+ // This static string table is all the eTLD domain names packed together.
+ static const union etld_strings {
+ struct etld_string_list list;
+ char strtab[1];
+ } strings;
+
+ // This is the static entries table. Each entry has an index into the string
+ // table. The entries are in sorted order so that binary search can be used.
+ static const ETLDEntry entries[];
+
+ void FuncForStaticAsserts(void);
+#undef ETLD_STR_NUM
+#undef ETLD_STR_NUM1
+};
+
+class nsEffectiveTLDService final
+ : public nsIEffectiveTLDService
+ , public nsIMemoryReporter
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIEFFECTIVETLDSERVICE
+ NS_DECL_NSIMEMORYREPORTER
+
+ nsEffectiveTLDService();
+ nsresult Init();
+
+ size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
+
+private:
+ nsresult GetBaseDomainInternal(nsCString &aHostname, int32_t aAdditionalParts, nsACString &aBaseDomain);
+ nsresult NormalizeHostname(nsCString &aHostname);
+ ~nsEffectiveTLDService();
+
+ nsCOMPtr<nsIIDNService> mIDNService;
+};
+
+#endif // EffectiveTLDService_h
diff --git a/netwerk/dns/nsHostResolver.cpp b/netwerk/dns/nsHostResolver.cpp
new file mode 100644
index 000000000..f2e26cadd
--- /dev/null
+++ b/netwerk/dns/nsHostResolver.cpp
@@ -0,0 +1,1579 @@
+/* vim:set ts=4 sw=4 sts=4 et cin: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#if defined(HAVE_RES_NINIT)
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#define RES_RETRY_ON_FAILURE
+#endif
+
+#include <stdlib.h>
+#include <ctime>
+#include "nsHostResolver.h"
+#include "nsError.h"
+#include "nsISupportsBase.h"
+#include "nsISupportsUtils.h"
+#include "nsAutoPtr.h"
+#include "nsPrintfCString.h"
+#include "prthread.h"
+#include "prerror.h"
+#include "prtime.h"
+#include "mozilla/Logging.h"
+#include "PLDHashTable.h"
+#include "plstr.h"
+#include "nsURLHelper.h"
+#include "nsThreadUtils.h"
+#include "GetAddrInfo.h"
+
+#include "mozilla/HashFunctions.h"
+#include "mozilla/TimeStamp.h"
+#include "mozilla/Telemetry.h"
+#include "mozilla/DebugOnly.h"
+#include "mozilla/Preferences.h"
+
+using namespace mozilla;
+using namespace mozilla::net;
+
+// None of our implementations expose a TTL for negative responses, so we use a
+// constant always.
+static const unsigned int NEGATIVE_RECORD_LIFETIME = 60;
+
+//----------------------------------------------------------------------------
+
+// Use a persistent thread pool in order to avoid spinning up new threads all the time.
+// In particular, thread creation results in a res_init() call from libc which is
+// quite expensive.
+//
+// The pool dynamically grows between 0 and MAX_RESOLVER_THREADS in size. New requests
+// go first to an idle thread. If that cannot be found and there are fewer than MAX_RESOLVER_THREADS
+// currently in the pool a new thread is created for high priority requests. If
+// the new request is at a lower priority a new thread will only be created if
+// there are fewer than HighThreadThreshold currently outstanding. If a thread cannot be
+// created or an idle thread located for the request it is queued.
+//
+// When the pool is greater than HighThreadThreshold in size a thread will be destroyed after
+// ShortIdleTimeoutSeconds of idle time. Smaller pools use LongIdleTimeoutSeconds for a
+// timeout period.
+
+#define HighThreadThreshold MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY
+#define LongIdleTimeoutSeconds 300 // for threads 1 -> HighThreadThreshold
+#define ShortIdleTimeoutSeconds 60 // for threads HighThreadThreshold+1 -> MAX_RESOLVER_THREADS
+
+static_assert(HighThreadThreshold <= MAX_RESOLVER_THREADS,
+ "High Thread Threshold should be less equal Maximum allowed thread");
+
+//----------------------------------------------------------------------------
+
+static LazyLogModule gHostResolverLog("nsHostResolver");
+#define LOG(args) MOZ_LOG(gHostResolverLog, mozilla::LogLevel::Debug, args)
+#define LOG_ENABLED() MOZ_LOG_TEST(gHostResolverLog, mozilla::LogLevel::Debug)
+
+#define LOG_HOST(host, interface) host, \
+ (interface && interface[0] != '\0') ? " on interface " : "", \
+ (interface && interface[0] != '\0') ? interface : ""
+
+//----------------------------------------------------------------------------
+
+static inline void
+MoveCList(PRCList &from, PRCList &to)
+{
+ if (!PR_CLIST_IS_EMPTY(&from)) {
+ to.next = from.next;
+ to.prev = from.prev;
+ to.next->prev = &to;
+ to.prev->next = &to;
+ PR_INIT_CLIST(&from);
+ }
+}
+
+//----------------------------------------------------------------------------
+
+#if defined(RES_RETRY_ON_FAILURE)
+
+// this class represents the resolver state for a given thread. if we
+// encounter a lookup failure, then we can invoke the Reset method on an
+// instance of this class to reset the resolver (in case /etc/resolv.conf
+// for example changed). this is mainly an issue on GNU systems since glibc
+// only reads in /etc/resolv.conf once per thread. it may be an issue on
+// other systems as well.
+
+class nsResState
+{
+public:
+ nsResState()
+ // initialize mLastReset to the time when this object
+ // is created. this means that a reset will not occur
+ // if a thread is too young. the alternative would be
+ // to initialize this to the beginning of time, so that
+ // the first failure would cause a reset, but since the
+ // thread would have just started up, it likely would
+ // already have current /etc/resolv.conf info.
+ : mLastReset(PR_IntervalNow())
+ {
+ }
+
+ bool Reset()
+ {
+ // reset no more than once per second
+ if (PR_IntervalToSeconds(PR_IntervalNow() - mLastReset) < 1)
+ return false;
+
+ LOG(("Calling 'res_ninit'.\n"));
+
+ mLastReset = PR_IntervalNow();
+ return (res_ninit(&_res) == 0);
+ }
+
+private:
+ PRIntervalTime mLastReset;
+};
+
+#endif // RES_RETRY_ON_FAILURE
+
+//----------------------------------------------------------------------------
+
+static inline bool
+IsHighPriority(uint16_t flags)
+{
+ return !(flags & (nsHostResolver::RES_PRIORITY_LOW | nsHostResolver::RES_PRIORITY_MEDIUM));
+}
+
+static inline bool
+IsMediumPriority(uint16_t flags)
+{
+ return flags & nsHostResolver::RES_PRIORITY_MEDIUM;
+}
+
+static inline bool
+IsLowPriority(uint16_t flags)
+{
+ return flags & nsHostResolver::RES_PRIORITY_LOW;
+}
+
+//----------------------------------------------------------------------------
+// this macro filters out any flags that are not used when constructing the
+// host key. the significant flags are those that would affect the resulting
+// host record (i.e., the flags that are passed down to PR_GetAddrInfoByName).
+#define RES_KEY_FLAGS(_f) ((_f) & nsHostResolver::RES_CANON_NAME)
+
+nsHostRecord::nsHostRecord(const nsHostKey *key)
+ : addr_info_lock("nsHostRecord.addr_info_lock")
+ , addr_info_gencnt(0)
+ , addr_info(nullptr)
+ , addr(nullptr)
+ , negative(false)
+ , resolving(false)
+ , onQueue(false)
+ , usingAnyThread(false)
+ , mDoomed(false)
+#if TTL_AVAILABLE
+ , mGetTtl(false)
+#endif
+ , mBlacklistedCount(0)
+ , mResolveAgain(false)
+{
+ host = ((char *) this) + sizeof(nsHostRecord);
+ memcpy((char *) host, key->host, strlen(key->host) + 1);
+ flags = key->flags;
+ af = key->af;
+ netInterface = host + strlen(key->host) + 1;
+ memcpy((char *) netInterface, key->netInterface,
+ strlen(key->netInterface) + 1);
+ PR_INIT_CLIST(this);
+ PR_INIT_CLIST(&callbacks);
+}
+
+nsresult
+nsHostRecord::Create(const nsHostKey *key, nsHostRecord **result)
+{
+ size_t hostLen = strlen(key->host) + 1;
+ size_t netInterfaceLen = strlen(key->netInterface) + 1;
+ size_t size = hostLen + netInterfaceLen + sizeof(nsHostRecord);
+
+ // Use placement new to create the object with room for the hostname and
+ // network interface name allocated after it.
+ void *place = ::operator new(size);
+ *result = new(place) nsHostRecord(key);
+ NS_ADDREF(*result);
+
+ return NS_OK;
+}
+
+void
+nsHostRecord::SetExpiration(const mozilla::TimeStamp& now, unsigned int valid, unsigned int grace)
+{
+ mValidStart = now;
+ mGraceStart = now + TimeDuration::FromSeconds(valid);
+ mValidEnd = now + TimeDuration::FromSeconds(valid + grace);
+}
+
+void
+nsHostRecord::CopyExpirationTimesAndFlagsFrom(const nsHostRecord *aFromHostRecord)
+{
+ // This is used to copy information from a cache entry to a record. All
+ // information necessary for HasUsableRecord needs to be copied.
+ mValidStart = aFromHostRecord->mValidStart;
+ mValidEnd = aFromHostRecord->mValidEnd;
+ mGraceStart = aFromHostRecord->mGraceStart;
+ mDoomed = aFromHostRecord->mDoomed;
+}
+
+nsHostRecord::~nsHostRecord()
+{
+ Telemetry::Accumulate(Telemetry::DNS_BLACKLIST_COUNT, mBlacklistedCount);
+ delete addr_info;
+ delete addr;
+}
+
+bool
+nsHostRecord::Blacklisted(NetAddr *aQuery)
+{
+ // must call locked
+ LOG(("Checking blacklist for host [%s%s%s], host record [%p].\n",
+ LOG_HOST(host, netInterface), this));
+
+ // skip the string conversion for the common case of no blacklist
+ if (!mBlacklistedItems.Length()) {
+ return false;
+ }
+
+ char buf[kIPv6CStrBufSize];
+ if (!NetAddrToString(aQuery, buf, sizeof(buf))) {
+ return false;
+ }
+ nsDependentCString strQuery(buf);
+
+ for (uint32_t i = 0; i < mBlacklistedItems.Length(); i++) {
+ if (mBlacklistedItems.ElementAt(i).Equals(strQuery)) {
+ LOG(("Address [%s] is blacklisted for host [%s%s%s].\n", buf,
+ LOG_HOST(host, netInterface)));
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void
+nsHostRecord::ReportUnusable(NetAddr *aAddress)
+{
+ // must call locked
+ LOG(("Adding address to blacklist for host [%s%s%s], host record [%p].\n",
+ LOG_HOST(host, netInterface), this));
+
+ ++mBlacklistedCount;
+
+ if (negative)
+ mDoomed = true;
+
+ char buf[kIPv6CStrBufSize];
+ if (NetAddrToString(aAddress, buf, sizeof(buf))) {
+ LOG(("Successfully adding address [%s] to blacklist for host "
+ "[%s%s%s].\n", buf, LOG_HOST(host, netInterface)));
+ mBlacklistedItems.AppendElement(nsCString(buf));
+ }
+}
+
+void
+nsHostRecord::ResetBlacklist()
+{
+ // must call locked
+ LOG(("Resetting blacklist for host [%s%s%s], host record [%p].\n",
+ LOG_HOST(host, netInterface), this));
+ mBlacklistedItems.Clear();
+}
+
+nsHostRecord::ExpirationStatus
+nsHostRecord::CheckExpiration(const mozilla::TimeStamp& now) const {
+ if (!mGraceStart.IsNull() && now >= mGraceStart
+ && !mValidEnd.IsNull() && now < mValidEnd) {
+ return nsHostRecord::EXP_GRACE;
+ } else if (!mValidEnd.IsNull() && now < mValidEnd) {
+ return nsHostRecord::EXP_VALID;
+ }
+
+ return nsHostRecord::EXP_EXPIRED;
+}
+
+
+bool
+nsHostRecord::HasUsableResult(const mozilla::TimeStamp& now, uint16_t queryFlags) const
+{
+ if (mDoomed) {
+ return false;
+ }
+
+ // don't use cached negative results for high priority queries.
+ if (negative && IsHighPriority(queryFlags)) {
+ return false;
+ }
+
+ if (CheckExpiration(now) == EXP_EXPIRED) {
+ return false;
+ }
+
+ return addr_info || addr || negative;
+}
+
+static size_t
+SizeOfResolveHostCallbackListExcludingHead(const PRCList *head,
+ MallocSizeOf mallocSizeOf)
+{
+ size_t n = 0;
+ PRCList *curr = head->next;
+ while (curr != head) {
+ nsResolveHostCallback *callback =
+ static_cast<nsResolveHostCallback*>(curr);
+ n += callback->SizeOfIncludingThis(mallocSizeOf);
+ curr = curr->next;
+ }
+ return n;
+}
+
+size_t
+nsHostRecord::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const
+{
+ size_t n = mallocSizeOf(this);
+
+ // The |host| field (inherited from nsHostKey) actually points to extra
+ // memory that is allocated beyond the end of the nsHostRecord (see
+ // nsHostRecord::Create()). So it will be included in the
+ // |mallocSizeOf(this)| call above.
+
+ n += SizeOfResolveHostCallbackListExcludingHead(&callbacks, mallocSizeOf);
+ n += addr_info ? addr_info->SizeOfIncludingThis(mallocSizeOf) : 0;
+ n += mallocSizeOf(addr);
+
+ n += mBlacklistedItems.ShallowSizeOfExcludingThis(mallocSizeOf);
+ for (size_t i = 0; i < mBlacklistedItems.Length(); i++) {
+ n += mBlacklistedItems[i].SizeOfExcludingThisIfUnshared(mallocSizeOf);
+ }
+ return n;
+}
+
+nsHostRecord::DnsPriority
+nsHostRecord::GetPriority(uint16_t aFlags)
+{
+ if (IsHighPriority(aFlags)){
+ return nsHostRecord::DNS_PRIORITY_HIGH;
+ } else if (IsMediumPriority(aFlags)) {
+ return nsHostRecord::DNS_PRIORITY_MEDIUM;
+ }
+
+ return nsHostRecord::DNS_PRIORITY_LOW;
+}
+
+// Returns true if the entry can be removed, or false if it should be left.
+// Sets mResolveAgain true for entries being resolved right now.
+bool
+nsHostRecord::RemoveOrRefresh()
+{
+ if (resolving) {
+ if (!onQueue) {
+ // The request has been passed to the OS resolver. The resultant DNS
+ // record should be considered stale and not trusted; set a flag to
+ // ensure it is called again.
+ mResolveAgain = true;
+ }
+ // if Onqueue is true, the host entry is already added to the cache
+ // but is still pending to get resolved: just leave it in hash.
+ return false;
+ }
+ // Already resolved; not in a pending state; remove from cache.
+ return true;
+}
+
+//----------------------------------------------------------------------------
+
+struct nsHostDBEnt : PLDHashEntryHdr
+{
+ nsHostRecord *rec;
+};
+
+static PLDHashNumber
+HostDB_HashKey(const void *key)
+{
+ const nsHostKey *hk = static_cast<const nsHostKey *>(key);
+ return AddToHash(HashString(hk->host), RES_KEY_FLAGS(hk->flags), hk->af,
+ HashString(hk->netInterface));
+}
+
+static bool
+HostDB_MatchEntry(const PLDHashEntryHdr *entry,
+ const void *key)
+{
+ const nsHostDBEnt *he = static_cast<const nsHostDBEnt *>(entry);
+ const nsHostKey *hk = static_cast<const nsHostKey *>(key);
+
+ return !strcmp(he->rec->host ? he->rec->host : "",
+ hk->host ? hk->host : "") &&
+ RES_KEY_FLAGS (he->rec->flags) == RES_KEY_FLAGS(hk->flags) &&
+ he->rec->af == hk->af &&
+ !strcmp(he->rec->netInterface, hk->netInterface);
+}
+
+static void
+HostDB_MoveEntry(PLDHashTable *table,
+ const PLDHashEntryHdr *from,
+ PLDHashEntryHdr *to)
+{
+ static_cast<nsHostDBEnt *>(to)->rec =
+ static_cast<const nsHostDBEnt *>(from)->rec;
+}
+
+static void
+HostDB_ClearEntry(PLDHashTable *table,
+ PLDHashEntryHdr *entry)
+{
+ nsHostDBEnt *he = static_cast<nsHostDBEnt*>(entry);
+ MOZ_ASSERT(he, "nsHostDBEnt is null!");
+
+ nsHostRecord *hr = he->rec;
+ MOZ_ASSERT(hr, "nsHostDBEnt has null host record!");
+
+ LOG(("Clearing cache db entry for host [%s%s%s].\n",
+ LOG_HOST(hr->host, hr->netInterface)));
+#if defined(DEBUG)
+ {
+ MutexAutoLock lock(hr->addr_info_lock);
+ if (!hr->addr_info) {
+ LOG(("No address info for host [%s%s%s].\n",
+ LOG_HOST(hr->host, hr->netInterface)));
+ } else {
+ if (!hr->mValidEnd.IsNull()) {
+ TimeDuration diff = hr->mValidEnd - TimeStamp::NowLoRes();
+ LOG(("Record for host [%s%s%s] expires in %f seconds.\n",
+ LOG_HOST(hr->host, hr->netInterface),
+ diff.ToSeconds()));
+ } else {
+ LOG(("Record for host [%s%s%s] not yet valid.\n",
+ LOG_HOST(hr->host, hr->netInterface)));
+ }
+
+ NetAddrElement *addrElement = nullptr;
+ char buf[kIPv6CStrBufSize];
+ do {
+ if (!addrElement) {
+ addrElement = hr->addr_info->mAddresses.getFirst();
+ } else {
+ addrElement = addrElement->getNext();
+ }
+
+ if (addrElement) {
+ NetAddrToString(&addrElement->mAddress, buf, sizeof(buf));
+ LOG((" [%s]\n", buf));
+ }
+ }
+ while (addrElement);
+ }
+ }
+#endif
+ NS_RELEASE(he->rec);
+}
+
+static void
+HostDB_InitEntry(PLDHashEntryHdr *entry,
+ const void *key)
+{
+ nsHostDBEnt *he = static_cast<nsHostDBEnt *>(entry);
+ nsHostRecord::Create(static_cast<const nsHostKey *>(key), &he->rec);
+}
+
+static const PLDHashTableOps gHostDB_ops =
+{
+ HostDB_HashKey,
+ HostDB_MatchEntry,
+ HostDB_MoveEntry,
+ HostDB_ClearEntry,
+ HostDB_InitEntry,
+};
+
+//----------------------------------------------------------------------------
+
+#if TTL_AVAILABLE
+static const char kPrefGetTtl[] = "network.dns.get-ttl";
+static bool sGetTtlEnabled = false;
+
+static void DnsPrefChanged(const char* aPref, void* aClosure)
+{
+ MOZ_ASSERT(NS_IsMainThread(),
+ "Should be getting pref changed notification on main thread!");
+
+ if (strcmp(aPref, kPrefGetTtl) != 0) {
+ LOG(("DnsPrefChanged ignoring pref \"%s\"", aPref));
+ return;
+ }
+
+ auto self = static_cast<nsHostResolver*>(aClosure);
+ MOZ_ASSERT(self);
+
+ sGetTtlEnabled = Preferences::GetBool(kPrefGetTtl);
+}
+#endif
+
+nsHostResolver::nsHostResolver(uint32_t maxCacheEntries,
+ uint32_t defaultCacheEntryLifetime,
+ uint32_t defaultGracePeriod)
+ : mMaxCacheEntries(maxCacheEntries)
+ , mDefaultCacheLifetime(defaultCacheEntryLifetime)
+ , mDefaultGracePeriod(defaultGracePeriod)
+ , mLock("nsHostResolver.mLock")
+ , mIdleThreadCV(mLock, "nsHostResolver.mIdleThreadCV")
+ , mDB(&gHostDB_ops, sizeof(nsHostDBEnt), 0)
+ , mEvictionQSize(0)
+ , mShutdown(true)
+ , mNumIdleThreads(0)
+ , mThreadCount(0)
+ , mActiveAnyThreadCount(0)
+ , mPendingCount(0)
+{
+ mCreationTime = PR_Now();
+ PR_INIT_CLIST(&mHighQ);
+ PR_INIT_CLIST(&mMediumQ);
+ PR_INIT_CLIST(&mLowQ);
+ PR_INIT_CLIST(&mEvictionQ);
+
+ mLongIdleTimeout = PR_SecondsToInterval(LongIdleTimeoutSeconds);
+ mShortIdleTimeout = PR_SecondsToInterval(ShortIdleTimeoutSeconds);
+}
+
+nsHostResolver::~nsHostResolver() = default;
+
+nsresult
+nsHostResolver::Init()
+{
+ if (NS_FAILED(GetAddrInfoInit())) {
+ return NS_ERROR_FAILURE;
+ }
+
+ mShutdown = false;
+
+#if TTL_AVAILABLE
+ // The preferences probably haven't been loaded from the disk yet, so we
+ // need to register a callback that will set up the experiment once they
+ // are. We also need to explicitly set a value for the props otherwise the
+ // callback won't be called.
+ {
+ DebugOnly<nsresult> rv = Preferences::RegisterCallbackAndCall(
+ &DnsPrefChanged, kPrefGetTtl, this);
+ NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+ "Could not register DNS TTL pref callback.");
+ }
+#endif
+
+#if defined(HAVE_RES_NINIT)
+ // We want to make sure the system is using the correct resolver settings,
+ // so we force it to reload those settings whenever we startup a subsequent
+ // nsHostResolver instance. We assume that there is no reason to do this
+ // for the first nsHostResolver instance since that is usually created
+ // during application startup.
+ static int initCount = 0;
+ if (initCount++ > 0) {
+ LOG(("Calling 'res_ninit'.\n"));
+ res_ninit(&_res);
+ }
+#endif
+ return NS_OK;
+}
+
+void
+nsHostResolver::ClearPendingQueue(PRCList *aPendingQ)
+{
+ // loop through pending queue, erroring out pending lookups.
+ if (!PR_CLIST_IS_EMPTY(aPendingQ)) {
+ PRCList *node = aPendingQ->next;
+ while (node != aPendingQ) {
+ nsHostRecord *rec = static_cast<nsHostRecord *>(node);
+ node = node->next;
+ OnLookupComplete(rec, NS_ERROR_ABORT, nullptr);
+ }
+ }
+}
+
+//
+// FlushCache() is what we call when the network has changed. We must not
+// trust names that were resolved before this change. They may resolve
+// differently now.
+//
+// This function removes all existing resolved host entries from the hash.
+// Names that are in the pending queues can be left there. Entries in the
+// cache that have 'Resolve' set true but not 'onQueue' are being resolved
+// right now, so we need to mark them to get re-resolved on completion!
+
+void
+nsHostResolver::FlushCache()
+{
+ MutexAutoLock lock(mLock);
+ mEvictionQSize = 0;
+
+ // Clear the evictionQ and remove all its corresponding entries from
+ // the cache first
+ if (!PR_CLIST_IS_EMPTY(&mEvictionQ)) {
+ PRCList *node = mEvictionQ.next;
+ while (node != &mEvictionQ) {
+ nsHostRecord *rec = static_cast<nsHostRecord *>(node);
+ node = node->next;
+ PR_REMOVE_AND_INIT_LINK(rec);
+ mDB.Remove((nsHostKey *) rec);
+ NS_RELEASE(rec);
+ }
+ }
+
+ // Refresh the cache entries that are resolving RIGHT now, remove the rest.
+ for (auto iter = mDB.Iter(); !iter.Done(); iter.Next()) {
+ auto entry = static_cast<nsHostDBEnt *>(iter.Get());
+ // Try to remove the record, or mark it for refresh.
+ if (entry->rec->RemoveOrRefresh()) {
+ PR_REMOVE_LINK(entry->rec);
+ iter.Remove();
+ }
+ }
+}
+
+void
+nsHostResolver::Shutdown()
+{
+ LOG(("Shutting down host resolver.\n"));
+
+#if TTL_AVAILABLE
+ {
+ DebugOnly<nsresult> rv = Preferences::UnregisterCallback(
+ &DnsPrefChanged, kPrefGetTtl, this);
+ NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+ "Could not unregister DNS TTL pref callback.");
+ }
+#endif
+
+ PRCList pendingQHigh, pendingQMed, pendingQLow, evictionQ;
+ PR_INIT_CLIST(&pendingQHigh);
+ PR_INIT_CLIST(&pendingQMed);
+ PR_INIT_CLIST(&pendingQLow);
+ PR_INIT_CLIST(&evictionQ);
+
+ {
+ MutexAutoLock lock(mLock);
+
+ mShutdown = true;
+
+ MoveCList(mHighQ, pendingQHigh);
+ MoveCList(mMediumQ, pendingQMed);
+ MoveCList(mLowQ, pendingQLow);
+ MoveCList(mEvictionQ, evictionQ);
+ mEvictionQSize = 0;
+ mPendingCount = 0;
+
+ if (mNumIdleThreads)
+ mIdleThreadCV.NotifyAll();
+
+ // empty host database
+ mDB.Clear();
+ }
+
+ ClearPendingQueue(&pendingQHigh);
+ ClearPendingQueue(&pendingQMed);
+ ClearPendingQueue(&pendingQLow);
+
+ if (!PR_CLIST_IS_EMPTY(&evictionQ)) {
+ PRCList *node = evictionQ.next;
+ while (node != &evictionQ) {
+ nsHostRecord *rec = static_cast<nsHostRecord *>(node);
+ node = node->next;
+ NS_RELEASE(rec);
+ }
+ }
+
+#ifdef NS_BUILD_REFCNT_LOGGING
+
+ // Logically join the outstanding worker threads with a timeout.
+ // Use this approach instead of PR_JoinThread() because that does
+ // not allow a timeout which may be necessary for a semi-responsive
+ // shutdown if the thread is blocked on a very slow DNS resolution.
+ // mThreadCount is read outside of mLock, but the worst case
+ // scenario for that race is one extra 25ms sleep.
+
+ PRIntervalTime delay = PR_MillisecondsToInterval(25);
+ PRIntervalTime stopTime = PR_IntervalNow() + PR_SecondsToInterval(20);
+ while (mThreadCount && PR_IntervalNow() < stopTime)
+ PR_Sleep(delay);
+#endif
+
+ {
+ mozilla::DebugOnly<nsresult> rv = GetAddrInfoShutdown();
+ NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+ "Failed to shutdown GetAddrInfo");
+ }
+}
+
+void
+nsHostResolver::MoveQueue(nsHostRecord *aRec, PRCList &aDestQ)
+{
+ NS_ASSERTION(aRec->onQueue, "Moving Host Record Not Currently Queued");
+
+ PR_REMOVE_LINK(aRec);
+ PR_APPEND_LINK(aRec, &aDestQ);
+}
+
+nsresult
+nsHostResolver::ResolveHost(const char *host,
+ uint16_t flags,
+ uint16_t af,
+ const char *netInterface,
+ nsResolveHostCallback *callback)
+{
+ NS_ENSURE_TRUE(host && *host, NS_ERROR_UNEXPECTED);
+ NS_ENSURE_TRUE(netInterface, NS_ERROR_UNEXPECTED);
+
+ LOG(("Resolving host [%s%s%s]%s.\n", LOG_HOST(host, netInterface),
+ flags & RES_BYPASS_CACHE ? " - bypassing cache" : ""));
+
+ // ensure that we are working with a valid hostname before proceeding. see
+ // bug 304904 for details.
+ if (!net_IsValidHostName(nsDependentCString(host)))
+ return NS_ERROR_UNKNOWN_HOST;
+
+ // if result is set inside the lock, then we need to issue the
+ // callback before returning.
+ RefPtr<nsHostRecord> result;
+ nsresult status = NS_OK, rv = NS_OK;
+ {
+ MutexAutoLock lock(mLock);
+
+ if (mShutdown)
+ rv = NS_ERROR_NOT_INITIALIZED;
+ else {
+ // Used to try to parse to an IP address literal.
+ PRNetAddr tempAddr;
+ // Unfortunately, PR_StringToNetAddr does not properly initialize
+ // the output buffer in the case of IPv6 input. See bug 223145.
+ memset(&tempAddr, 0, sizeof(PRNetAddr));
+
+ // check to see if there is already an entry for this |host|
+ // in the hash table. if so, then check to see if we can't
+ // just reuse the lookup result. otherwise, if there are
+ // any pending callbacks, then add to pending callbacks queue,
+ // and return. otherwise, add ourselves as first pending
+ // callback, and proceed to do the lookup.
+
+ nsHostKey key = { host, flags, af, netInterface };
+ auto he = static_cast<nsHostDBEnt*>(mDB.Add(&key, fallible));
+
+ // if the record is null, the hash table OOM'd.
+ if (!he) {
+ LOG((" Out of memory: no cache entry for host [%s%s%s].\n",
+ LOG_HOST(host, netInterface)));
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ // do we have a cached result that we can reuse?
+ else if (!(flags & RES_BYPASS_CACHE) &&
+ he->rec->HasUsableResult(TimeStamp::NowLoRes(), flags)) {
+ LOG((" Using cached record for host [%s%s%s].\n",
+ LOG_HOST(host, netInterface)));
+ // put reference to host record on stack...
+ result = he->rec;
+ Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2, METHOD_HIT);
+
+ // For entries that are in the grace period
+ // or all cached negative entries, use the cache but start a new
+ // lookup in the background
+ ConditionallyRefreshRecord(he->rec, host);
+
+ if (he->rec->negative) {
+ LOG((" Negative cache entry for host [%s%s%s].\n",
+ LOG_HOST(host, netInterface)));
+ Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
+ METHOD_NEGATIVE_HIT);
+ status = NS_ERROR_UNKNOWN_HOST;
+ }
+ }
+ // if the host name is an IP address literal and has been parsed,
+ // go ahead and use it.
+ else if (he->rec->addr) {
+ LOG((" Using cached address for IP Literal [%s].\n", host));
+ Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
+ METHOD_LITERAL);
+ result = he->rec;
+ }
+ // try parsing the host name as an IP address literal to short
+ // circuit full host resolution. (this is necessary on some
+ // platforms like Win9x. see bug 219376 for more details.)
+ else if (PR_StringToNetAddr(host, &tempAddr) == PR_SUCCESS) {
+ LOG((" Host is IP Literal [%s].\n", host));
+ // ok, just copy the result into the host record, and be done
+ // with it! ;-)
+ he->rec->addr = new NetAddr();
+ PRNetAddrToNetAddr(&tempAddr, he->rec->addr);
+ // put reference to host record on stack...
+ Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
+ METHOD_LITERAL);
+ result = he->rec;
+ }
+ else if (mPendingCount >= MAX_NON_PRIORITY_REQUESTS &&
+ !IsHighPriority(flags) &&
+ !he->rec->resolving) {
+ LOG((" Lookup queue full: dropping %s priority request for "
+ "host [%s%s%s].\n",
+ IsMediumPriority(flags) ? "medium" : "low",
+ LOG_HOST(host, netInterface)));
+ Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
+ METHOD_OVERFLOW);
+ // This is a lower priority request and we are swamped, so refuse it.
+ rv = NS_ERROR_DNS_LOOKUP_QUEUE_FULL;
+ }
+ else if (flags & RES_OFFLINE) {
+ LOG((" Offline request for host [%s%s%s]; ignoring.\n",
+ LOG_HOST(host, netInterface)));
+ rv = NS_ERROR_OFFLINE;
+ }
+
+ // If this is an IPV4 or IPV6 specific request, check if there is
+ // an AF_UNSPEC entry we can use. Otherwise, hit the resolver...
+ else if (!he->rec->resolving) {
+ if (!(flags & RES_BYPASS_CACHE) &&
+ ((af == PR_AF_INET) || (af == PR_AF_INET6))) {
+ // First, search for an entry with AF_UNSPEC
+ const nsHostKey unspecKey = { host, flags, PR_AF_UNSPEC,
+ netInterface };
+ auto unspecHe =
+ static_cast<nsHostDBEnt*>(mDB.Search(&unspecKey));
+ NS_ASSERTION(!unspecHe ||
+ (unspecHe && unspecHe->rec),
+ "Valid host entries should contain a record");
+ TimeStamp now = TimeStamp::NowLoRes();
+ if (unspecHe &&
+ unspecHe->rec->HasUsableResult(now, flags)) {
+
+ MOZ_ASSERT(unspecHe->rec->addr_info || unspecHe->rec->negative,
+ "Entry should be resolved or negative.");
+
+ LOG((" Trying AF_UNSPEC entry for host [%s%s%s] af: %s.\n",
+ LOG_HOST(host, netInterface),
+ (af == PR_AF_INET) ? "AF_INET" : "AF_INET6"));
+
+ he->rec->addr_info = nullptr;
+ if (unspecHe->rec->negative) {
+ he->rec->negative = unspecHe->rec->negative;
+ he->rec->CopyExpirationTimesAndFlagsFrom(unspecHe->rec);
+ } else if (unspecHe->rec->addr_info) {
+ // Search for any valid address in the AF_UNSPEC entry
+ // in the cache (not blacklisted and from the right
+ // family).
+ NetAddrElement *addrIter =
+ unspecHe->rec->addr_info->mAddresses.getFirst();
+ while (addrIter) {
+ if ((af == addrIter->mAddress.inet.family) &&
+ !unspecHe->rec->Blacklisted(&addrIter->mAddress)) {
+ if (!he->rec->addr_info) {
+ he->rec->addr_info = new AddrInfo(
+ unspecHe->rec->addr_info->mHostName,
+ unspecHe->rec->addr_info->mCanonicalName);
+ he->rec->CopyExpirationTimesAndFlagsFrom(unspecHe->rec);
+ }
+ he->rec->addr_info->AddAddress(
+ new NetAddrElement(*addrIter));
+ }
+ addrIter = addrIter->getNext();
+ }
+ }
+ // Now check if we have a new record.
+ if (he->rec->HasUsableResult(now, flags)) {
+ result = he->rec;
+ if (he->rec->negative) {
+ status = NS_ERROR_UNKNOWN_HOST;
+ }
+ Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
+ METHOD_HIT);
+ ConditionallyRefreshRecord(he->rec, host);
+ }
+ // For AF_INET6, a new lookup means another AF_UNSPEC
+ // lookup. We have already iterated through the
+ // AF_UNSPEC addresses, so we mark this record as
+ // negative.
+ else if (af == PR_AF_INET6) {
+ LOG((" No AF_INET6 in AF_UNSPEC entry: "
+ "host [%s%s%s] unknown host.",
+ LOG_HOST(host, netInterface)));
+ result = he->rec;
+ he->rec->negative = true;
+ status = NS_ERROR_UNKNOWN_HOST;
+ Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
+ METHOD_NEGATIVE_HIT);
+ }
+ }
+ }
+ // If no valid address was found in the cache or this is an
+ // AF_UNSPEC request, then start a new lookup.
+ if (!result) {
+ LOG((" No usable address in cache for host [%s%s%s].",
+ LOG_HOST(host, netInterface)));
+
+ // Add callback to the list of pending callbacks.
+ PR_APPEND_LINK(callback, &he->rec->callbacks);
+ he->rec->flags = flags;
+ rv = IssueLookup(he->rec);
+ Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
+ METHOD_NETWORK_FIRST);
+ if (NS_FAILED(rv)) {
+ PR_REMOVE_AND_INIT_LINK(callback);
+ }
+ else {
+ LOG((" DNS lookup for host [%s%s%s] blocking "
+ "pending 'getaddrinfo' query: callback [%p]",
+ LOG_HOST(host, netInterface), callback));
+ }
+ }
+ }
+ else {
+ LOG((" Host [%s%s%s] is being resolved. Appending callback "
+ "[%p].", LOG_HOST(host, netInterface), callback));
+
+ PR_APPEND_LINK(callback, &he->rec->callbacks);
+ if (he->rec->onQueue) {
+ Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
+ METHOD_NETWORK_SHARED);
+
+ // Consider the case where we are on a pending queue of
+ // lower priority than the request is being made at.
+ // In that case we should upgrade to the higher queue.
+
+ if (IsHighPriority(flags) &&
+ !IsHighPriority(he->rec->flags)) {
+ // Move from (low|med) to high.
+ MoveQueue(he->rec, mHighQ);
+ he->rec->flags = flags;
+ ConditionallyCreateThread(he->rec);
+ } else if (IsMediumPriority(flags) &&
+ IsLowPriority(he->rec->flags)) {
+ // Move from low to med.
+ MoveQueue(he->rec, mMediumQ);
+ he->rec->flags = flags;
+ mIdleThreadCV.Notify();
+ }
+ }
+ }
+ }
+ }
+ if (result) {
+ callback->OnLookupComplete(this, result, status);
+ }
+
+ return rv;
+}
+
+void
+nsHostResolver::DetachCallback(const char *host,
+ uint16_t flags,
+ uint16_t af,
+ const char *netInterface,
+ nsResolveHostCallback *callback,
+ nsresult status)
+{
+ RefPtr<nsHostRecord> rec;
+ {
+ MutexAutoLock lock(mLock);
+
+ nsHostKey key = { host, flags, af, netInterface };
+ auto he = static_cast<nsHostDBEnt*>(mDB.Search(&key));
+ if (he) {
+ // walk list looking for |callback|... we cannot assume
+ // that it will be there!
+ PRCList *node = he->rec->callbacks.next;
+ while (node != &he->rec->callbacks) {
+ if (static_cast<nsResolveHostCallback *>(node) == callback) {
+ PR_REMOVE_LINK(callback);
+ rec = he->rec;
+ break;
+ }
+ node = node->next;
+ }
+ }
+ }
+
+ // complete callback with the given status code; this would only be done if
+ // the record was in the process of being resolved.
+ if (rec)
+ callback->OnLookupComplete(this, rec, status);
+}
+
+nsresult
+nsHostResolver::ConditionallyCreateThread(nsHostRecord *rec)
+{
+ if (mNumIdleThreads) {
+ // wake up idle thread to process this lookup
+ mIdleThreadCV.Notify();
+ }
+ else if ((mThreadCount < HighThreadThreshold) ||
+ (IsHighPriority(rec->flags) && mThreadCount < MAX_RESOLVER_THREADS)) {
+ // dispatch new worker thread
+ NS_ADDREF_THIS(); // owning reference passed to thread
+
+ mThreadCount++;
+ PRThread *thr = PR_CreateThread(PR_SYSTEM_THREAD,
+ ThreadFunc,
+ this,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_UNJOINABLE_THREAD,
+ 0);
+ if (!thr) {
+ mThreadCount--;
+ NS_RELEASE_THIS();
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+ else {
+ LOG((" Unable to find a thread for looking up host [%s%s%s].\n",
+ LOG_HOST(rec->host, rec->netInterface)));
+ }
+ return NS_OK;
+}
+
+nsresult
+nsHostResolver::IssueLookup(nsHostRecord *rec)
+{
+ nsresult rv = NS_OK;
+ NS_ASSERTION(!rec->resolving, "record is already being resolved");
+
+ // Add rec to one of the pending queues, possibly removing it from mEvictionQ.
+ // If rec is on mEvictionQ, then we can just move the owning
+ // reference over to the new active queue.
+ if (rec->next == rec)
+ NS_ADDREF(rec);
+ else {
+ PR_REMOVE_LINK(rec);
+ mEvictionQSize--;
+ }
+
+ switch (nsHostRecord::GetPriority(rec->flags)) {
+ case nsHostRecord::DNS_PRIORITY_HIGH:
+ PR_APPEND_LINK(rec, &mHighQ);
+ break;
+
+ case nsHostRecord::DNS_PRIORITY_MEDIUM:
+ PR_APPEND_LINK(rec, &mMediumQ);
+ break;
+
+ case nsHostRecord::DNS_PRIORITY_LOW:
+ PR_APPEND_LINK(rec, &mLowQ);
+ break;
+ }
+ mPendingCount++;
+
+ rec->resolving = true;
+ rec->onQueue = true;
+
+ rv = ConditionallyCreateThread(rec);
+
+ LOG ((" DNS thread counters: total=%d any-live=%d idle=%d pending=%d\n",
+ static_cast<uint32_t>(mThreadCount),
+ static_cast<uint32_t>(mActiveAnyThreadCount),
+ static_cast<uint32_t>(mNumIdleThreads),
+ static_cast<uint32_t>(mPendingCount)));
+
+ return rv;
+}
+
+nsresult
+nsHostResolver::ConditionallyRefreshRecord(nsHostRecord *rec, const char *host)
+{
+ if ((rec->CheckExpiration(TimeStamp::NowLoRes()) != nsHostRecord::EXP_VALID
+ || rec->negative) && !rec->resolving) {
+ LOG((" Using %s cache entry for host [%s] but starting async renewal.",
+ rec->negative ? "negative" :"positive", host));
+ IssueLookup(rec);
+
+ if (!rec->negative) {
+ // negative entries are constantly being refreshed, only
+ // track positive grace period induced renewals
+ Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
+ METHOD_RENEWAL);
+ }
+ }
+ return NS_OK;
+}
+
+void
+nsHostResolver::DeQueue(PRCList &aQ, nsHostRecord **aResult)
+{
+ *aResult = static_cast<nsHostRecord *>(aQ.next);
+ PR_REMOVE_AND_INIT_LINK(*aResult);
+ mPendingCount--;
+ (*aResult)->onQueue = false;
+}
+
+bool
+nsHostResolver::GetHostToLookup(nsHostRecord **result)
+{
+ bool timedOut = false;
+ PRIntervalTime epoch, now, timeout;
+
+ MutexAutoLock lock(mLock);
+
+ timeout = (mNumIdleThreads >= HighThreadThreshold) ? mShortIdleTimeout : mLongIdleTimeout;
+ epoch = PR_IntervalNow();
+
+ while (!mShutdown) {
+ // remove next record from Q; hand over owning reference. Check high, then med, then low
+
+#if TTL_AVAILABLE
+ #define SET_GET_TTL(var, val) \
+ (var)->mGetTtl = sGetTtlEnabled && (val)
+#else
+ #define SET_GET_TTL(var, val)
+#endif
+
+ if (!PR_CLIST_IS_EMPTY(&mHighQ)) {
+ DeQueue (mHighQ, result);
+ SET_GET_TTL(*result, false);
+ return true;
+ }
+
+ if (mActiveAnyThreadCount < HighThreadThreshold) {
+ if (!PR_CLIST_IS_EMPTY(&mMediumQ)) {
+ DeQueue (mMediumQ, result);
+ mActiveAnyThreadCount++;
+ (*result)->usingAnyThread = true;
+ SET_GET_TTL(*result, true);
+ return true;
+ }
+
+ if (!PR_CLIST_IS_EMPTY(&mLowQ)) {
+ DeQueue (mLowQ, result);
+ mActiveAnyThreadCount++;
+ (*result)->usingAnyThread = true;
+ SET_GET_TTL(*result, true);
+ return true;
+ }
+ }
+
+ // Determining timeout is racy, so allow one cycle through checking the queues
+ // before exiting.
+ if (timedOut)
+ break;
+
+ // wait for one or more of the following to occur:
+ // (1) the pending queue has a host record to process
+ // (2) the shutdown flag has been set
+ // (3) the thread has been idle for too long
+
+ mNumIdleThreads++;
+ mIdleThreadCV.Wait(timeout);
+ mNumIdleThreads--;
+
+ now = PR_IntervalNow();
+
+ if ((PRIntervalTime)(now - epoch) >= timeout)
+ timedOut = true;
+ else {
+ // It is possible that PR_WaitCondVar() was interrupted and returned early,
+ // in which case we will loop back and re-enter it. In that case we want to
+ // do so with the new timeout reduced to reflect time already spent waiting.
+ timeout -= (PRIntervalTime)(now - epoch);
+ epoch = now;
+ }
+ }
+
+ // tell thread to exit...
+ return false;
+}
+
+void
+nsHostResolver::PrepareRecordExpiration(nsHostRecord* rec) const
+{
+ MOZ_ASSERT(((bool)rec->addr_info) != rec->negative);
+ if (!rec->addr_info) {
+ rec->SetExpiration(TimeStamp::NowLoRes(),
+ NEGATIVE_RECORD_LIFETIME, 0);
+ LOG(("Caching host [%s%s%s] negative record for %u seconds.\n",
+ LOG_HOST(rec->host, rec->netInterface),
+ NEGATIVE_RECORD_LIFETIME));
+ return;
+ }
+
+ unsigned int lifetime = mDefaultCacheLifetime;
+ unsigned int grace = mDefaultGracePeriod;
+#if TTL_AVAILABLE
+ unsigned int ttl = mDefaultCacheLifetime;
+ if (sGetTtlEnabled) {
+ MutexAutoLock lock(rec->addr_info_lock);
+ if (rec->addr_info && rec->addr_info->ttl != AddrInfo::NO_TTL_DATA) {
+ ttl = rec->addr_info->ttl;
+ }
+ lifetime = ttl;
+ grace = 0;
+ }
+#endif
+
+ rec->SetExpiration(TimeStamp::NowLoRes(), lifetime, grace);
+ LOG(("Caching host [%s%s%s] record for %u seconds (grace %d).",
+ LOG_HOST(rec->host, rec->netInterface), lifetime, grace));
+}
+
+static bool
+different_rrset(AddrInfo *rrset1, AddrInfo *rrset2)
+{
+ if (!rrset1 || !rrset2) {
+ return true;
+ }
+
+ LOG(("different_rrset %s\n", rrset1->mHostName));
+ nsTArray<NetAddr> orderedSet1;
+ nsTArray<NetAddr> orderedSet2;
+
+ for (NetAddrElement *element = rrset1->mAddresses.getFirst();
+ element; element = element->getNext()) {
+ if (LOG_ENABLED()) {
+ char buf[128];
+ NetAddrToString(&element->mAddress, buf, 128);
+ LOG(("different_rrset add to set 1 %s\n", buf));
+ }
+ orderedSet1.InsertElementAt(orderedSet1.Length(), element->mAddress);
+ }
+
+ for (NetAddrElement *element = rrset2->mAddresses.getFirst();
+ element; element = element->getNext()) {
+ if (LOG_ENABLED()) {
+ char buf[128];
+ NetAddrToString(&element->mAddress, buf, 128);
+ LOG(("different_rrset add to set 2 %s\n", buf));
+ }
+ orderedSet2.InsertElementAt(orderedSet2.Length(), element->mAddress);
+ }
+
+ if (orderedSet1.Length() != orderedSet2.Length()) {
+ LOG(("different_rrset true due to length change\n"));
+ return true;
+ }
+ orderedSet1.Sort();
+ orderedSet2.Sort();
+
+ for (uint32_t i = 0; i < orderedSet1.Length(); ++i) {
+ if (!(orderedSet1[i] == orderedSet2[i])) {
+ LOG(("different_rrset true due to content change\n"));
+ return true;
+ }
+ }
+ LOG(("different_rrset false\n"));
+ return false;
+}
+
+//
+// OnLookupComplete() checks if the resolving should be redone and if so it
+// returns LOOKUP_RESOLVEAGAIN, but only if 'status' is not NS_ERROR_ABORT.
+// takes ownership of AddrInfo parameter
+nsHostResolver::LookupStatus
+nsHostResolver::OnLookupComplete(nsHostRecord* rec, nsresult status, AddrInfo* newRRSet)
+{
+ // get the list of pending callbacks for this lookup, and notify
+ // them that the lookup is complete.
+ PRCList cbs;
+ PR_INIT_CLIST(&cbs);
+ {
+ MutexAutoLock lock(mLock);
+
+ if (rec->mResolveAgain && (status != NS_ERROR_ABORT)) {
+ LOG(("nsHostResolver record %p resolve again due to flushcache\n", rec));
+ rec->mResolveAgain = false;
+ delete newRRSet;
+ return LOOKUP_RESOLVEAGAIN;
+ }
+
+ // grab list of callbacks to notify
+ MoveCList(rec->callbacks, cbs);
+
+ // update record fields. We might have a rec->addr_info already if a
+ // previous lookup result expired and we're reresolving it..
+ AddrInfo *old_addr_info;
+ {
+ MutexAutoLock lock(rec->addr_info_lock);
+ if (different_rrset(rec->addr_info, newRRSet)) {
+ LOG(("nsHostResolver record %p new gencnt\n", rec));
+ old_addr_info = rec->addr_info;
+ rec->addr_info = newRRSet;
+ rec->addr_info_gencnt++;
+ } else {
+ if (rec->addr_info && newRRSet) {
+ rec->addr_info->ttl = newRRSet->ttl;
+ }
+ old_addr_info = newRRSet;
+ }
+ }
+ delete old_addr_info;
+
+ rec->negative = !rec->addr_info;
+ PrepareRecordExpiration(rec);
+ rec->resolving = false;
+
+ if (rec->usingAnyThread) {
+ mActiveAnyThreadCount--;
+ rec->usingAnyThread = false;
+ }
+
+ if (!mShutdown) {
+ // add to mEvictionQ
+ PR_APPEND_LINK(rec, &mEvictionQ);
+ NS_ADDREF(rec);
+ if (mEvictionQSize < mMaxCacheEntries)
+ mEvictionQSize++;
+ else {
+ // remove first element on mEvictionQ
+ nsHostRecord *head =
+ static_cast<nsHostRecord *>(PR_LIST_HEAD(&mEvictionQ));
+ PR_REMOVE_AND_INIT_LINK(head);
+ mDB.Remove((nsHostKey *) head);
+
+ if (!head->negative) {
+ // record the age of the entry upon eviction.
+ TimeDuration age = TimeStamp::NowLoRes() - head->mValidStart;
+ Telemetry::Accumulate(Telemetry::DNS_CLEANUP_AGE,
+ static_cast<uint32_t>(age.ToSeconds() / 60));
+ }
+
+ // release reference to rec owned by mEvictionQ
+ NS_RELEASE(head);
+ }
+#if TTL_AVAILABLE
+ if (!rec->mGetTtl && !rec->resolving && sGetTtlEnabled) {
+ LOG(("Issuing second async lookup for TTL for host [%s%s%s].",
+ LOG_HOST(rec->host, rec->netInterface)));
+ rec->flags =
+ (rec->flags & ~RES_PRIORITY_MEDIUM) | RES_PRIORITY_LOW;
+ DebugOnly<nsresult> rv = IssueLookup(rec);
+ NS_WARNING_ASSERTION(
+ NS_SUCCEEDED(rv),
+ "Could not issue second async lookup for TTL.");
+ }
+#endif
+ }
+ }
+
+ if (!PR_CLIST_IS_EMPTY(&cbs)) {
+ PRCList *node = cbs.next;
+ while (node != &cbs) {
+ nsResolveHostCallback *callback =
+ static_cast<nsResolveHostCallback *>(node);
+ node = node->next;
+ callback->OnLookupComplete(this, rec, status);
+ // NOTE: callback must not be dereferenced after this point!!
+ }
+ }
+
+ NS_RELEASE(rec);
+
+ return LOOKUP_OK;
+}
+
+void
+nsHostResolver::CancelAsyncRequest(const char *host,
+ uint16_t flags,
+ uint16_t af,
+ const char *netInterface,
+ nsIDNSListener *aListener,
+ nsresult status)
+
+{
+ MutexAutoLock lock(mLock);
+
+ // Lookup the host record associated with host, flags & address family
+ nsHostKey key = { host, flags, af, netInterface };
+ auto he = static_cast<nsHostDBEnt*>(mDB.Search(&key));
+ if (he) {
+ nsHostRecord* recPtr = nullptr;
+ PRCList *node = he->rec->callbacks.next;
+ // Remove the first nsDNSAsyncRequest callback which matches the
+ // supplied listener object
+ while (node != &he->rec->callbacks) {
+ nsResolveHostCallback *callback
+ = static_cast<nsResolveHostCallback *>(node);
+ if (callback && (callback->EqualsAsyncListener(aListener))) {
+ // Remove from the list of callbacks
+ PR_REMOVE_LINK(callback);
+ recPtr = he->rec;
+ callback->OnLookupComplete(this, recPtr, status);
+ break;
+ }
+ node = node->next;
+ }
+
+ // If there are no more callbacks, remove the hash table entry
+ if (recPtr && PR_CLIST_IS_EMPTY(&recPtr->callbacks)) {
+ mDB.Remove((nsHostKey *)recPtr);
+ // If record is on a Queue, remove it and then deref it
+ if (recPtr->next != recPtr) {
+ PR_REMOVE_LINK(recPtr);
+ NS_RELEASE(recPtr);
+ }
+ }
+ }
+}
+
+size_t
+nsHostResolver::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const
+{
+ MutexAutoLock lock(mLock);
+
+ size_t n = mallocSizeOf(this);
+
+ n += mDB.ShallowSizeOfExcludingThis(mallocSizeOf);
+ for (auto iter = mDB.ConstIter(); !iter.Done(); iter.Next()) {
+ auto entry = static_cast<nsHostDBEnt*>(iter.Get());
+ n += entry->rec->SizeOfIncludingThis(mallocSizeOf);
+ }
+
+ // The following fields aren't measured.
+ // - mHighQ, mMediumQ, mLowQ, mEvictionQ, because they just point to
+ // nsHostRecords that also pointed to by entries |mDB|, and measured when
+ // |mDB| is measured.
+
+ return n;
+}
+
+void
+nsHostResolver::ThreadFunc(void *arg)
+{
+ LOG(("DNS lookup thread - starting execution.\n"));
+
+ static nsThreadPoolNaming naming;
+ naming.SetThreadPoolName(NS_LITERAL_CSTRING("DNS Resolver"));
+
+#if defined(RES_RETRY_ON_FAILURE)
+ nsResState rs;
+#endif
+ nsHostResolver *resolver = (nsHostResolver *)arg;
+ nsHostRecord *rec = nullptr;
+ AddrInfo *ai = nullptr;
+
+ while (rec || resolver->GetHostToLookup(&rec)) {
+ LOG(("DNS lookup thread - Calling getaddrinfo for host [%s%s%s].\n",
+ LOG_HOST(rec->host, rec->netInterface)));
+
+ TimeStamp startTime = TimeStamp::Now();
+#if TTL_AVAILABLE
+ bool getTtl = rec->mGetTtl;
+#else
+ bool getTtl = false;
+#endif
+
+ nsresult status = GetAddrInfo(rec->host, rec->af, rec->flags, rec->netInterface,
+ &ai, getTtl);
+#if defined(RES_RETRY_ON_FAILURE)
+ if (NS_FAILED(status) && rs.Reset()) {
+ status = GetAddrInfo(rec->host, rec->af, rec->flags, rec->netInterface, &ai,
+ getTtl);
+ }
+#endif
+
+ { // obtain lock to check shutdown and manage inter-module telemetry
+ MutexAutoLock lock(resolver->mLock);
+
+ if (!resolver->mShutdown) {
+ TimeDuration elapsed = TimeStamp::Now() - startTime;
+ uint32_t millis = static_cast<uint32_t>(elapsed.ToMilliseconds());
+
+ if (NS_SUCCEEDED(status)) {
+ Telemetry::ID histogramID;
+ if (!rec->addr_info_gencnt) {
+ // Time for initial lookup.
+ histogramID = Telemetry::DNS_LOOKUP_TIME;
+ } else if (!getTtl) {
+ // Time for renewal; categorized by expiration strategy.
+ histogramID = Telemetry::DNS_RENEWAL_TIME;
+ } else {
+ // Time to get TTL; categorized by expiration strategy.
+ histogramID = Telemetry::DNS_RENEWAL_TIME_FOR_TTL;
+ }
+ Telemetry::Accumulate(histogramID, millis);
+ } else {
+ Telemetry::Accumulate(Telemetry::DNS_FAILED_LOOKUP_TIME, millis);
+ }
+ }
+ }
+
+ // OnLookupComplete may release "rec", long before we lose it.
+ LOG(("DNS lookup thread - lookup completed for host [%s%s%s]: %s.\n",
+ LOG_HOST(rec->host, rec->netInterface),
+ ai ? "success" : "failure: unknown host"));
+
+ if (LOOKUP_RESOLVEAGAIN == resolver->OnLookupComplete(rec, status, ai)) {
+ // leave 'rec' assigned and loop to make a renewed host resolve
+ LOG(("DNS lookup thread - Re-resolving host [%s%s%s].\n",
+ LOG_HOST(rec->host, rec->netInterface)));
+ } else {
+ rec = nullptr;
+ }
+ }
+ resolver->mThreadCount--;
+ NS_RELEASE(resolver);
+ LOG(("DNS lookup thread - queue empty, thread finished.\n"));
+}
+
+nsresult
+nsHostResolver::Create(uint32_t maxCacheEntries,
+ uint32_t defaultCacheEntryLifetime,
+ uint32_t defaultGracePeriod,
+ nsHostResolver **result)
+{
+ auto *res = new nsHostResolver(maxCacheEntries, defaultCacheEntryLifetime,
+ defaultGracePeriod);
+ NS_ADDREF(res);
+
+ nsresult rv = res->Init();
+ if (NS_FAILED(rv))
+ NS_RELEASE(res);
+
+ *result = res;
+ return rv;
+}
+
+void
+nsHostResolver::GetDNSCacheEntries(nsTArray<DNSCacheEntries> *args)
+{
+ for (auto iter = mDB.Iter(); !iter.Done(); iter.Next()) {
+ // We don't pay attention to address literals, only resolved domains.
+ // Also require a host.
+ auto entry = static_cast<nsHostDBEnt*>(iter.Get());
+ nsHostRecord* rec = entry->rec;
+ MOZ_ASSERT(rec, "rec should never be null here!");
+ if (!rec || !rec->addr_info || !rec->host) {
+ continue;
+ }
+
+ DNSCacheEntries info;
+ info.hostname = rec->host;
+ info.family = rec->af;
+ info.netInterface = rec->netInterface;
+ info.expiration =
+ (int64_t)(rec->mValidEnd - TimeStamp::NowLoRes()).ToSeconds();
+ if (info.expiration <= 0) {
+ // We only need valid DNS cache entries
+ continue;
+ }
+
+ {
+ MutexAutoLock lock(rec->addr_info_lock);
+
+ NetAddr *addr = nullptr;
+ NetAddrElement *addrElement = rec->addr_info->mAddresses.getFirst();
+ if (addrElement) {
+ addr = &addrElement->mAddress;
+ }
+ while (addr) {
+ char buf[kIPv6CStrBufSize];
+ if (NetAddrToString(addr, buf, sizeof(buf))) {
+ info.hostaddr.AppendElement(buf);
+ }
+ addr = nullptr;
+ addrElement = addrElement->getNext();
+ if (addrElement) {
+ addr = &addrElement->mAddress;
+ }
+ }
+ }
+
+ args->AppendElement(info);
+ }
+}
diff --git a/netwerk/dns/nsHostResolver.h b/netwerk/dns/nsHostResolver.h
new file mode 100644
index 000000000..4c37ff0d3
--- /dev/null
+++ b/netwerk/dns/nsHostResolver.h
@@ -0,0 +1,372 @@
+/* vim:set ts=4 sw=4 sts=4 et cin: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsHostResolver_h__
+#define nsHostResolver_h__
+
+#include "nscore.h"
+#include "prclist.h"
+#include "prnetdb.h"
+#include "PLDHashTable.h"
+#include "mozilla/CondVar.h"
+#include "mozilla/Mutex.h"
+#include "nsISupportsImpl.h"
+#include "nsIDNSListener.h"
+#include "nsIDNSService.h"
+#include "nsString.h"
+#include "nsTArray.h"
+#include "GetAddrInfo.h"
+#include "mozilla/net/DNS.h"
+#include "mozilla/net/DashboardTypes.h"
+#include "mozilla/TimeStamp.h"
+
+class nsHostResolver;
+class nsHostRecord;
+class nsResolveHostCallback;
+
+#define MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY 3
+#define MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY 5
+#define MAX_NON_PRIORITY_REQUESTS 150
+
+#define MAX_RESOLVER_THREADS (MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY + \
+ MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY)
+
+struct nsHostKey
+{
+ const char *host;
+ uint16_t flags;
+ uint16_t af;
+ const char *netInterface;
+};
+
+/**
+ * nsHostRecord - ref counted object type stored in host resolver cache.
+ */
+class nsHostRecord : public PRCList, public nsHostKey
+{
+ typedef mozilla::Mutex Mutex;
+
+public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsHostRecord)
+
+ /* instantiates a new host record */
+ static nsresult Create(const nsHostKey *key, nsHostRecord **record);
+
+ /* a fully resolved host record has either a non-null |addr_info| or |addr|
+ * field. if |addr_info| is null, it implies that the |host| is an IP
+ * address literal. in which case, |addr| contains the parsed address.
+ * otherwise, if |addr_info| is non-null, then it contains one or many
+ * IP addresses corresponding to the given host name. if both |addr_info|
+ * and |addr| are null, then the given host has not yet been fully resolved.
+ * |af| is the address family of the record we are querying for.
+ */
+
+ /* the lock protects |addr_info| and |addr_info_gencnt| because they
+ * are mutable and accessed by the resolver worker thread and the
+ * nsDNSService2 class. |addr| doesn't change after it has been
+ * assigned a value. only the resolver worker thread modifies
+ * nsHostRecord (and only in nsHostResolver::OnLookupComplete);
+ * the other threads just read it. therefore the resolver worker
+ * thread doesn't need to lock when reading |addr_info|.
+ */
+ Mutex addr_info_lock;
+ int addr_info_gencnt; /* generation count of |addr_info| */
+ mozilla::net::AddrInfo *addr_info;
+ mozilla::net::NetAddr *addr;
+ bool negative; /* True if this record is a cache of a failed lookup.
+ Negative cache entries are valid just like any other
+ (though never for more than 60 seconds), but a use
+ of that negative entry forces an asynchronous refresh. */
+
+ enum ExpirationStatus {
+ EXP_VALID,
+ EXP_GRACE,
+ EXP_EXPIRED,
+ };
+
+ ExpirationStatus CheckExpiration(const mozilla::TimeStamp& now) const;
+
+ // When the record began being valid. Used mainly for bookkeeping.
+ mozilla::TimeStamp mValidStart;
+
+ // When the record is no longer valid (it's time of expiration)
+ mozilla::TimeStamp mValidEnd;
+
+ // When the record enters its grace period. This must be before mValidEnd.
+ // If a record is in its grace period (and not expired), it will be used
+ // but a request to refresh it will be made.
+ mozilla::TimeStamp mGraceStart;
+
+ // Convenience function for setting the timestamps above (mValidStart,
+ // mValidEnd, and mGraceStart). valid and grace are durations in seconds.
+ void SetExpiration(const mozilla::TimeStamp& now, unsigned int valid,
+ unsigned int grace);
+ void CopyExpirationTimesAndFlagsFrom(const nsHostRecord *aFromHostRecord);
+
+ // Checks if the record is usable (not expired and has a value)
+ bool HasUsableResult(const mozilla::TimeStamp& now, uint16_t queryFlags = 0) const;
+
+ // hold addr_info_lock when calling the blacklist functions
+ bool Blacklisted(mozilla::net::NetAddr *query);
+ void ResetBlacklist();
+ void ReportUnusable(mozilla::net::NetAddr *addr);
+
+ size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
+
+ enum DnsPriority {
+ DNS_PRIORITY_LOW,
+ DNS_PRIORITY_MEDIUM,
+ DNS_PRIORITY_HIGH,
+ };
+ static DnsPriority GetPriority(uint16_t aFlags);
+
+ bool RemoveOrRefresh(); // Mark records currently being resolved as needed
+ // to resolve again.
+
+private:
+ friend class nsHostResolver;
+
+
+ PRCList callbacks; /* list of callbacks */
+
+ bool resolving; /* true if this record is being resolved, which means
+ * that it is either on the pending queue or owned by
+ * one of the worker threads. */
+
+ bool onQueue; /* true if pending and on the queue (not yet given to getaddrinfo())*/
+ bool usingAnyThread; /* true if off queue and contributing to mActiveAnyThreadCount */
+ bool mDoomed; /* explicitly expired */
+
+#if TTL_AVAILABLE
+ bool mGetTtl;
+#endif
+
+ // The number of times ReportUnusable() has been called in the record's
+ // lifetime.
+ uint32_t mBlacklistedCount;
+
+ // when the results from this resolve is returned, it is not to be
+ // trusted, but instead a new resolve must be made!
+ bool mResolveAgain;
+
+ // a list of addresses associated with this record that have been reported
+ // as unusable. the list is kept as a set of strings to make it independent
+ // of gencnt.
+ nsTArray<nsCString> mBlacklistedItems;
+
+ explicit nsHostRecord(const nsHostKey *key); /* use Create() instead */
+ ~nsHostRecord();
+};
+
+/**
+ * ResolveHost callback object. It's PRCList members are used by
+ * the nsHostResolver and should not be used by anything else.
+ */
+class NS_NO_VTABLE nsResolveHostCallback : public PRCList
+{
+public:
+ /**
+ * OnLookupComplete
+ *
+ * this function is called to complete a host lookup initiated by
+ * nsHostResolver::ResolveHost. it may be invoked recursively from
+ * ResolveHost or on an unspecified background thread.
+ *
+ * NOTE: it is the responsibility of the implementor of this method
+ * to handle the callback in a thread safe manner.
+ *
+ * @param resolver
+ * nsHostResolver object associated with this result
+ * @param record
+ * the host record containing the results of the lookup
+ * @param status
+ * if successful, |record| contains non-null results
+ */
+ virtual void OnLookupComplete(nsHostResolver *resolver,
+ nsHostRecord *record,
+ nsresult status) = 0;
+ /**
+ * EqualsAsyncListener
+ *
+ * Determines if the listener argument matches the listener member var.
+ * For subclasses not implementing a member listener, should return false.
+ * For subclasses having a member listener, the function should check if
+ * they are the same. Used for cases where a pointer to an object
+ * implementing nsResolveHostCallback is unknown, but a pointer to
+ * the original listener is known.
+ *
+ * @param aListener
+ * nsIDNSListener object associated with the original request
+ */
+ virtual bool EqualsAsyncListener(nsIDNSListener *aListener) = 0;
+
+ virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf) const = 0;
+};
+
+/**
+ * nsHostResolver - an asynchronous host name resolver.
+ */
+class nsHostResolver
+{
+ typedef mozilla::CondVar CondVar;
+ typedef mozilla::Mutex Mutex;
+
+public:
+ /**
+ * host resolver instances are reference counted.
+ */
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsHostResolver)
+
+ /**
+ * creates an addref'd instance of a nsHostResolver object.
+ */
+ static nsresult Create(uint32_t maxCacheEntries, // zero disables cache
+ uint32_t defaultCacheEntryLifetime, // seconds
+ uint32_t defaultGracePeriod, // seconds
+ nsHostResolver **resolver);
+
+ /**
+ * puts the resolver in the shutdown state, which will cause any pending
+ * callbacks to be detached. any future calls to ResolveHost will fail.
+ */
+ void Shutdown();
+
+ /**
+ * resolve the given hostname asynchronously. the caller can synthesize
+ * a synchronous host lookup using a lock and a cvar. as noted above
+ * the callback will occur re-entrantly from an unspecified thread. the
+ * host lookup cannot be canceled (cancelation can be layered above this
+ * by having the callback implementation return without doing anything).
+ */
+ nsresult ResolveHost(const char *hostname,
+ uint16_t flags,
+ uint16_t af,
+ const char *netInterface,
+ nsResolveHostCallback *callback);
+
+ /**
+ * removes the specified callback from the nsHostRecord for the given
+ * hostname, flags, and address family. these parameters should correspond
+ * to the parameters passed to ResolveHost. this function executes the
+ * callback if the callback is still pending with the given status.
+ */
+ void DetachCallback(const char *hostname,
+ uint16_t flags,
+ uint16_t af,
+ const char *netInterface,
+ nsResolveHostCallback *callback,
+ nsresult status);
+
+ /**
+ * Cancels an async request associated with the hostname, flags,
+ * address family and listener. Cancels first callback found which matches
+ * these criteria. These parameters should correspond to the parameters
+ * passed to ResolveHost. If this is the last callback associated with the
+ * host record, it is removed from any request queues it might be on.
+ */
+ void CancelAsyncRequest(const char *host,
+ uint16_t flags,
+ uint16_t af,
+ const char *netInterface,
+ nsIDNSListener *aListener,
+ nsresult status);
+ /**
+ * values for the flags parameter passed to ResolveHost and DetachCallback
+ * that may be bitwise OR'd together.
+ *
+ * NOTE: in this implementation, these flags correspond exactly in value
+ * to the flags defined on nsIDNSService.
+ */
+ enum {
+ RES_BYPASS_CACHE = nsIDNSService::RESOLVE_BYPASS_CACHE,
+ RES_CANON_NAME = nsIDNSService::RESOLVE_CANONICAL_NAME,
+ RES_PRIORITY_MEDIUM = nsIDNSService::RESOLVE_PRIORITY_MEDIUM,
+ RES_PRIORITY_LOW = nsIDNSService::RESOLVE_PRIORITY_LOW,
+ RES_SPECULATE = nsIDNSService::RESOLVE_SPECULATE,
+ //RES_DISABLE_IPV6 = nsIDNSService::RESOLVE_DISABLE_IPV6, // Not used
+ RES_OFFLINE = nsIDNSService::RESOLVE_OFFLINE,
+ //RES_DISABLE_IPv4 = nsIDNSService::RESOLVE_DISABLE_IPV4, // Not Used
+ RES_ALLOW_NAME_COLLISION = nsIDNSService::RESOLVE_ALLOW_NAME_COLLISION
+ };
+
+ size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
+
+ /**
+ * Flush the DNS cache.
+ */
+ void FlushCache();
+
+private:
+ explicit nsHostResolver(uint32_t maxCacheEntries,
+ uint32_t defaultCacheEntryLifetime,
+ uint32_t defaultGracePeriod);
+ ~nsHostResolver();
+
+ nsresult Init();
+ nsresult IssueLookup(nsHostRecord *);
+ bool GetHostToLookup(nsHostRecord **m);
+
+ enum LookupStatus {
+ LOOKUP_OK,
+ LOOKUP_RESOLVEAGAIN,
+ };
+
+ LookupStatus OnLookupComplete(nsHostRecord *, nsresult, mozilla::net::AddrInfo *);
+ void DeQueue(PRCList &aQ, nsHostRecord **aResult);
+ void ClearPendingQueue(PRCList *aPendingQueue);
+ nsresult ConditionallyCreateThread(nsHostRecord *rec);
+
+ /**
+ * Starts a new lookup in the background for entries that are in the grace
+ * period with a failed connect or all cached entries are negative.
+ */
+ nsresult ConditionallyRefreshRecord(nsHostRecord *rec, const char *host);
+
+ static void MoveQueue(nsHostRecord *aRec, PRCList &aDestQ);
+
+ static void ThreadFunc(void *);
+
+ enum {
+ METHOD_HIT = 1,
+ METHOD_RENEWAL = 2,
+ METHOD_NEGATIVE_HIT = 3,
+ METHOD_LITERAL = 4,
+ METHOD_OVERFLOW = 5,
+ METHOD_NETWORK_FIRST = 6,
+ METHOD_NETWORK_SHARED = 7
+ };
+
+ uint32_t mMaxCacheEntries;
+ uint32_t mDefaultCacheLifetime; // granularity seconds
+ uint32_t mDefaultGracePeriod; // granularity seconds
+ mutable Mutex mLock; // mutable so SizeOfIncludingThis can be const
+ CondVar mIdleThreadCV;
+ PLDHashTable mDB;
+ PRCList mHighQ;
+ PRCList mMediumQ;
+ PRCList mLowQ;
+ PRCList mEvictionQ;
+ uint32_t mEvictionQSize;
+ PRTime mCreationTime;
+ PRIntervalTime mLongIdleTimeout;
+ PRIntervalTime mShortIdleTimeout;
+
+ mozilla::Atomic<bool> mShutdown;
+ mozilla::Atomic<uint32_t> mNumIdleThreads;
+ mozilla::Atomic<uint32_t> mThreadCount;
+ mozilla::Atomic<uint32_t> mActiveAnyThreadCount;
+ mozilla::Atomic<uint32_t> mPendingCount;
+
+ // Set the expiration time stamps appropriately.
+ void PrepareRecordExpiration(nsHostRecord* rec) const;
+
+public:
+ /*
+ * Called by the networking dashboard via the DnsService2
+ */
+ void GetDNSCacheEntries(nsTArray<mozilla::net::DNSCacheEntries> *);
+};
+
+#endif // nsHostResolver_h__
diff --git a/netwerk/dns/nsIDNKitInterface.h b/netwerk/dns/nsIDNKitInterface.h
new file mode 100644
index 000000000..3e1ae7a73
--- /dev/null
+++ b/netwerk/dns/nsIDNKitInterface.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved.
+ *
+ * By using this file, you agree to the terms and conditions set forth bellow.
+ *
+ * LICENSE TERMS AND CONDITIONS
+ *
+ * The following License Terms and Conditions apply, unless a different
+ * license is obtained from Japan Network Information Center ("JPNIC"),
+ * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
+ * Chiyoda-ku, Tokyo 101-0047, Japan.
+
+ * 1. Use, Modification and Redistribution (including distribution of any
+ * modified or derived work) in source and/or binary forms is permitted
+ * under this License Terms and Conditions.
+ *
+ * 2. Redistribution of source code must retain the copyright notices as they
+ * appear in each source code file, this License Terms and Conditions.
+ *
+ * 3. Redistribution in binary form must reproduce the Copyright Notice,
+ * this License Terms and Conditions, in the documentation and/or other
+ * materials provided with the distribution. For the purposes of binary
+ * distribution the "Copyright Notice" refers to the following language:
+ * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
+ *
+ * 4. The name of JPNIC may not be used to endorse or promote products
+ * derived from this Software without specific prior written approval of
+ * JPNIC.
+ *
+ * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef nsIDNKitWrapper_h__
+#define nsIDNKitWrapper_h__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * libidnkit result code.
+ */
+typedef enum {
+ idn_success,
+ idn_notfound,
+ idn_invalid_encoding,
+ idn_invalid_syntax,
+ idn_invalid_name,
+ idn_invalid_message,
+ idn_invalid_action,
+ idn_invalid_codepoint,
+ idn_invalid_length,
+ idn_buffer_overflow,
+ idn_noentry,
+ idn_nomemory,
+ idn_nofile,
+ idn_nomapping,
+ idn_context_required,
+ idn_prohibited,
+ idn_failure /* !!This must be the last one!! */
+} idn_result_t;
+
+/*
+ * BIDI type codes.
+ */
+typedef enum {
+ idn_biditype_r_al,
+ idn_biditype_l,
+ idn_biditype_others
+} idn_biditype_t;
+
+/*
+ * A Handle for nameprep operations.
+ */
+typedef struct idn_nameprep *idn_nameprep_t;
+
+
+/*
+ * The latest version of nameprep.
+ */
+#define IDN_NAMEPREP_CURRENT "nameprep-11"
+
+#undef assert
+#define assert(a)
+#define TRACE(a)
+
+
+/* race.c */
+idn_result_t race_decode_decompress(const char *from,
+ uint16_t *buf,
+ size_t buflen);
+idn_result_t race_compress_encode(const uint16_t *p,
+ int compress_mode,
+ char *to, size_t tolen);
+int get_compress_mode(uint16_t *p);
+
+
+/* nameprep.c */
+
+/*
+ * Create a handle for nameprep operations.
+ * The handle is stored in '*handlep', which is used other functions
+ * in this module.
+ * The version of the NAMEPREP specification can be specified with
+ * 'version' parameter. If 'version' is nullptr, the latest version
+ * is used.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_notfound -- specified version not found.
+ */
+idn_result_t
+idn_nameprep_create(const char *version, idn_nameprep_t *handlep);
+
+/*
+ * Close a handle, which was created by 'idn_nameprep_create'.
+ */
+void
+idn_nameprep_destroy(idn_nameprep_t handle);
+
+/*
+ * Perform character mapping on an UCS4 string specified by 'from', and
+ * store the result into 'to', whose length is specified by 'tolen'.
+ *
+ * Returns:
+ * idn_success -- ok.
+ * idn_buffer_overflow -- result buffer is too small.
+ */
+idn_result_t
+idn_nameprep_map(idn_nameprep_t handle, const uint32_t *from,
+ uint32_t *to, size_t tolen);
+
+/*
+ * Check if an UCS4 string 'str' contains any prohibited characters specified
+ * by the draft. If found, the pointer to the first such character is stored
+ * into '*found'. Otherwise '*found' will be nullptr.
+ *
+ * Returns:
+ * idn_success -- check has been done properly. (But this
+ * does not mean that no prohibited character
+ * was found. Check '*found' to see the
+ * result.)
+ */
+idn_result_t
+idn_nameprep_isprohibited(idn_nameprep_t handle, const uint32_t *str,
+ const uint32_t **found);
+
+/*
+ * Check if an UCS4 string 'str' contains any unassigned characters specified
+ * by the draft. If found, the pointer to the first such character is stored
+ * into '*found'. Otherwise '*found' will be nullptr.
+ *
+ * Returns:
+ * idn_success -- check has been done properly. (But this
+ * does not mean that no unassinged character
+ * was found. Check '*found' to see the
+ * result.)
+ */
+idn_result_t
+idn_nameprep_isunassigned(idn_nameprep_t handle, const uint32_t *str,
+ const uint32_t **found);
+
+/*
+ * Check if an UCS4 string 'str' is valid string specified by ``bidi check''
+ * of the draft. If it is not valid, the pointer to the first invalid
+ * character is stored into '*found'. Otherwise '*found' will be nullptr.
+ *
+ * Returns:
+ * idn_success -- check has been done properly. (But this
+ * does not mean that the string was valid.
+ * Check '*found' to see the result.)
+ */
+idn_result_t
+idn_nameprep_isvalidbidi(idn_nameprep_t handle, const uint32_t *str,
+ const uint32_t **found);
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* nsIDNKitWrapper_h__ */
diff --git a/netwerk/dns/nsIDNSListener.idl b/netwerk/dns/nsIDNSListener.idl
new file mode 100644
index 000000000..46c241005
--- /dev/null
+++ b/netwerk/dns/nsIDNSListener.idl
@@ -0,0 +1,46 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+interface nsICancelable;
+interface nsIDNSRecord;
+
+/**
+ * nsIDNSListener
+ */
+[scriptable, function, uuid(27d49bfe-280c-49e0-bbaa-f6200c232c3d)]
+interface nsIDNSListener : nsISupports
+{
+ /**
+ * called when an asynchronous host lookup completes.
+ *
+ * @param aRequest
+ * the value returned from asyncResolve.
+ * @param aRecord
+ * the DNS record corresponding to the hostname that was resolved.
+ * this parameter is null if there was an error.
+ * @param aStatus
+ * if the lookup failed, this parameter gives the reason.
+ */
+ void onLookupComplete(in nsICancelable aRequest,
+ in nsIDNSRecord aRecord,
+ in nsresult aStatus);
+};
+
+/**
+ * nsIDNSListenerProxy:
+ *
+ * Must be implemented by classes that wrap the original listener passed to
+ * nsIDNSService.AsyncResolve, so we have access to original listener for
+ * comparison purposes.
+ */
+[uuid(60eff0e4-6f7c-493c-add9-1cbea59063ad)]
+interface nsIDNSListenerProxy : nsISupports
+{
+ /*
+ * The original nsIDNSListener which requested hostname resolution.
+ */
+ readonly attribute nsIDNSListener originalListener;
+};
diff --git a/netwerk/dns/nsIDNSRecord.idl b/netwerk/dns/nsIDNSRecord.idl
new file mode 100644
index 000000000..b3158bd3b
--- /dev/null
+++ b/netwerk/dns/nsIDNSRecord.idl
@@ -0,0 +1,100 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+%{ C++
+namespace mozilla {
+namespace net {
+union NetAddr;
+}
+}
+#include "nsTArrayForwardDeclare.h"
+%}
+native NetAddr(mozilla::net::NetAddr);
+[ref] native nsNetAddrTArrayRef(nsTArray<mozilla::net::NetAddr>);
+interface nsINetAddr;
+
+/**
+ * nsIDNSRecord
+ *
+ * this interface represents the result of a DNS lookup. since a DNS
+ * query may return more than one resolved IP address, the record acts
+ * like an enumerator, allowing the caller to easily step through the
+ * list of IP addresses.
+ */
+[scriptable, uuid(f92228ae-c417-4188-a604-0830a95e7eb9)]
+interface nsIDNSRecord : nsISupports
+{
+ /**
+ * @return the canonical hostname for this record. this value is empty if
+ * the record was not fetched with the RESOLVE_CANONICAL_NAME flag.
+ *
+ * e.g., www.mozilla.org --> rheet.mozilla.org
+ */
+ readonly attribute ACString canonicalName;
+
+ /**
+ * this function copies the value of the next IP address into the
+ * given NetAddr struct and increments the internal address iterator.
+ *
+ * @param aPort
+ * A port number to initialize the NetAddr with.
+ *
+ * @throws NS_ERROR_NOT_AVAILABLE if there is not another IP address in
+ * the record.
+ */
+ [noscript] NetAddr getNextAddr(in uint16_t aPort);
+
+ /**
+ * this function copies the value of all working members of the RR
+ * set into the output array.
+ *
+ * @param aAddressArray
+ * The result set
+ */
+ [noscript] void getAddresses(out nsNetAddrTArrayRef aAddressArray);
+
+ /**
+ * this function returns the value of the next IP address as a
+ * scriptable address and increments the internal address iterator.
+ *
+ * @param aPort
+ * A port number to initialize the nsINetAddr with.
+ *
+ * @throws NS_ERROR_NOT_AVAILABLE if there is not another IP address in
+ * the record.
+ */
+ nsINetAddr getScriptableNextAddr(in uint16_t aPort);
+
+ /**
+ * this function returns the value of the next IP address as a
+ * string and increments the internal address iterator.
+ *
+ * @throws NS_ERROR_NOT_AVAILABLE if there is not another IP address in
+ * the record.
+ */
+ ACString getNextAddrAsString();
+
+ /**
+ * this function returns true if there is another address in the record.
+ */
+ boolean hasMore();
+
+ /**
+ * this function resets the internal address iterator to the first
+ * address in the record.
+ */
+ void rewind();
+
+ /**
+ * This function indicates that the last address obtained via getNextAddr*()
+ * was not usuable and should be skipped in future uses of this
+ * record if other addresses are available.
+ *
+ * @param aPort is the port number associated with the failure, if any.
+ * It may be zero if not applicable.
+ */
+ void reportUnusable(in uint16_t aPort);
+};
diff --git a/netwerk/dns/nsIDNSService.idl b/netwerk/dns/nsIDNSService.idl
new file mode 100644
index 000000000..2704790dc
--- /dev/null
+++ b/netwerk/dns/nsIDNSService.idl
@@ -0,0 +1,171 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+interface nsICancelable;
+interface nsIEventTarget;
+interface nsIDNSRecord;
+interface nsIDNSListener;
+
+%{C++
+#include "nsTArrayForwardDeclare.h"
+namespace mozilla { namespace net {
+ struct DNSCacheEntries;
+} }
+%}
+
+[ptr] native EntriesArray(nsTArray<mozilla::net::DNSCacheEntries>);
+
+/**
+ * nsIDNSService
+ */
+[scriptable, uuid(de5642c6-61fc-4fcf-9a47-03226b0d4e21)]
+interface nsIDNSService : nsISupports
+{
+ /**
+ * kicks off an asynchronous host lookup.
+ *
+ * @param aHostName
+ * the hostname or IP-address-literal to resolve.
+ * @param aFlags
+ * a bitwise OR of the RESOLVE_ prefixed constants defined below.
+ * @param aListener
+ * the listener to be notified when the result is available.
+ * @param aListenerTarget
+ * optional parameter (may be null). if non-null, this parameter
+ * specifies the nsIEventTarget of the thread on which the
+ * listener's onLookupComplete should be called. however, if this
+ * parameter is null, then onLookupComplete will be called on an
+ * unspecified thread (possibly recursively).
+ *
+ * @return An object that can be used to cancel the host lookup.
+ */
+ nsICancelable asyncResolve(in AUTF8String aHostName,
+ in unsigned long aFlags,
+ in nsIDNSListener aListener,
+ in nsIEventTarget aListenerTarget);
+
+ /**
+ * Attempts to cancel a previously requested async DNS lookup
+ *
+ * @param aHostName
+ * the hostname or IP-address-literal to resolve.
+ * @param aFlags
+ * a bitwise OR of the RESOLVE_ prefixed constants defined below.
+ * @param aListener
+ * the original listener which was to be notified about the host lookup
+ * result - used to match request information to requestor.
+ * @param aReason
+ * nsresult reason for the cancellation
+ *
+ * @return An object that can be used to cancel the host lookup.
+ */
+ void cancelAsyncResolve(in AUTF8String aHostName,
+ in unsigned long aFlags,
+ in nsIDNSListener aListener,
+ in nsresult aReason);
+
+ /**
+ * called to synchronously resolve a hostname. warning this method may
+ * block the calling thread for a long period of time. it is extremely
+ * unwise to call this function on the UI thread of an application.
+ *
+ * @param aHostName
+ * the hostname or IP-address-literal to resolve.
+ * @param aFlags
+ * a bitwise OR of the RESOLVE_ prefixed constants defined below.
+ *
+ * @return DNS record corresponding to the given hostname.
+ * @throws NS_ERROR_UNKNOWN_HOST if host could not be resolved.
+ */
+ nsIDNSRecord resolve(in AUTF8String aHostName,
+ in unsigned long aFlags);
+
+ /**
+ * kicks off an asynchronous host lookup.
+ *
+ * This function is identical to asyncResolve except an additional
+ * parameter aNetwortInterface. If parameter aNetworkInterface is an empty
+ * string function will return the same result as asyncResolve.
+ * Setting aNetworkInterface value make only sense for gonk,because it
+ * an per networking interface query is possible.
+ */
+ nsICancelable asyncResolveExtended(in AUTF8String aHostName,
+ in unsigned long aFlags,
+ in AUTF8String aNetworkInterface,
+ in nsIDNSListener aListener,
+ in nsIEventTarget aListenerTarget);
+
+ /**
+ * Attempts to cancel a previously requested async DNS lookup
+ * This is an extended versin with a additional parameter aNetworkInterface
+ */
+ void cancelAsyncResolveExtended(in AUTF8String aHostName,
+ in unsigned long aFlags,
+ in AUTF8String aNetworkInterface,
+ in nsIDNSListener aListener,
+ in nsresult aReason);
+
+ /**
+ * The method takes a pointer to an nsTArray
+ * and fills it with cache entry data
+ * Called by the networking dashboard
+ */
+ [noscript] void getDNSCacheEntries(in EntriesArray args);
+
+ /**
+ * @return the hostname of the operating system.
+ */
+ readonly attribute AUTF8String myHostName;
+
+ /*************************************************************************
+ * Listed below are the various flags that may be OR'd together to form
+ * the aFlags parameter passed to asyncResolve() and resolve().
+ */
+
+ /**
+ * if set, this flag suppresses the internal DNS lookup cache.
+ */
+ const unsigned long RESOLVE_BYPASS_CACHE = (1 << 0);
+
+ /**
+ * if set, the canonical name of the specified host will be queried.
+ */
+ const unsigned long RESOLVE_CANONICAL_NAME = (1 << 1);
+
+ /**
+ * if set, the query is given lower priority. Medium takes precedence
+ * if both are used.
+ */
+ const unsigned long RESOLVE_PRIORITY_MEDIUM = (1 << 2);
+ const unsigned long RESOLVE_PRIORITY_LOW = (1 << 3);
+
+ /**
+ * if set, indicates request is speculative. Speculative requests
+ * return errors if prefetching is disabled by configuration.
+ */
+ const unsigned long RESOLVE_SPECULATE = (1 << 4);
+
+ /**
+ * If set, only IPv4 addresses will be returned from resolve/asyncResolve.
+ */
+ const unsigned long RESOLVE_DISABLE_IPV6 = (1 << 5);
+
+ /**
+ * If set, only literals and cached entries will be returned from resolve/
+ * asyncResolve.
+ */
+ const unsigned long RESOLVE_OFFLINE = (1 << 6);
+
+ /**
+ * If set, only IPv6 addresses will be returned from resolve/asyncResolve.
+ */
+ const unsigned long RESOLVE_DISABLE_IPV4 = (1 << 7);
+
+ /**
+ * If set, allow name collision results (127.0.53.53) which are normally filtered.
+ */
+ const unsigned long RESOLVE_ALLOW_NAME_COLLISION = (1 << 8);
+};
diff --git a/netwerk/dns/nsIDNService.cpp b/netwerk/dns/nsIDNService.cpp
new file mode 100644
index 000000000..d4f31027e
--- /dev/null
+++ b/netwerk/dns/nsIDNService.cpp
@@ -0,0 +1,959 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIDNService.h"
+#include "nsReadableUtils.h"
+#include "nsCRT.h"
+#include "nsUnicharUtils.h"
+#include "nsUnicodeProperties.h"
+#include "nsUnicodeScriptCodes.h"
+#include "harfbuzz/hb.h"
+#include "nsIServiceManager.h"
+#include "nsIPrefService.h"
+#include "nsIPrefBranch.h"
+#include "nsIObserverService.h"
+#include "nsISupportsPrimitives.h"
+#include "punycode.h"
+
+#ifdef IDNA2008
+// Currently we use the non-transitional processing option -- see
+// http://unicode.org/reports/tr46/
+// To switch to transitional processing, change the value of this flag
+// and kTransitionalProcessing in netwerk/test/unit/test_idna2008.js to true
+// (revert bug 1218179).
+const bool kIDNA2008_TransitionalProcessing = false;
+
+#include "ICUUtils.h"
+#endif
+
+using namespace mozilla::unicode;
+
+//-----------------------------------------------------------------------------
+// RFC 1034 - 3.1. Name space specifications and terminology
+static const uint32_t kMaxDNSNodeLen = 63;
+// RFC 3490 - 5. ACE prefix
+static const char kACEPrefix[] = "xn--";
+#define kACEPrefixLen 4
+
+//-----------------------------------------------------------------------------
+
+#define NS_NET_PREF_IDNBLACKLIST "network.IDN.blacklist_chars"
+#define NS_NET_PREF_SHOWPUNYCODE "network.IDN_show_punycode"
+#define NS_NET_PREF_IDNWHITELIST "network.IDN.whitelist."
+#define NS_NET_PREF_IDNUSEWHITELIST "network.IDN.use_whitelist"
+#define NS_NET_PREF_IDNRESTRICTION "network.IDN.restriction_profile"
+
+inline bool isOnlySafeChars(const nsAFlatString& in,
+ const nsAFlatString& blacklist)
+{
+ return (blacklist.IsEmpty() ||
+ in.FindCharInSet(blacklist) == kNotFound);
+}
+
+//-----------------------------------------------------------------------------
+// nsIDNService
+//-----------------------------------------------------------------------------
+
+/* Implementation file */
+NS_IMPL_ISUPPORTS(nsIDNService,
+ nsIIDNService,
+ nsIObserver,
+ nsISupportsWeakReference)
+
+nsresult nsIDNService::Init()
+{
+ nsCOMPtr<nsIPrefService> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
+ if (prefs)
+ prefs->GetBranch(NS_NET_PREF_IDNWHITELIST, getter_AddRefs(mIDNWhitelistPrefBranch));
+
+ nsCOMPtr<nsIPrefBranch> prefInternal(do_QueryInterface(prefs));
+ if (prefInternal) {
+ prefInternal->AddObserver(NS_NET_PREF_IDNBLACKLIST, this, true);
+ prefInternal->AddObserver(NS_NET_PREF_SHOWPUNYCODE, this, true);
+ prefInternal->AddObserver(NS_NET_PREF_IDNRESTRICTION, this, true);
+ prefInternal->AddObserver(NS_NET_PREF_IDNUSEWHITELIST, this, true);
+ prefsChanged(prefInternal, nullptr);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsIDNService::Observe(nsISupports *aSubject,
+ const char *aTopic,
+ const char16_t *aData)
+{
+ if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
+ nsCOMPtr<nsIPrefBranch> prefBranch( do_QueryInterface(aSubject) );
+ if (prefBranch)
+ prefsChanged(prefBranch, aData);
+ }
+ return NS_OK;
+}
+
+void nsIDNService::prefsChanged(nsIPrefBranch *prefBranch, const char16_t *pref)
+{
+ if (!pref || NS_LITERAL_STRING(NS_NET_PREF_IDNBLACKLIST).Equals(pref)) {
+ nsCOMPtr<nsISupportsString> blacklist;
+ nsresult rv = prefBranch->GetComplexValue(NS_NET_PREF_IDNBLACKLIST,
+ NS_GET_IID(nsISupportsString),
+ getter_AddRefs(blacklist));
+ if (NS_SUCCEEDED(rv))
+ blacklist->ToString(getter_Copies(mIDNBlacklist));
+ else
+ mIDNBlacklist.Truncate();
+ }
+ if (!pref || NS_LITERAL_STRING(NS_NET_PREF_SHOWPUNYCODE).Equals(pref)) {
+ bool val;
+ if (NS_SUCCEEDED(prefBranch->GetBoolPref(NS_NET_PREF_SHOWPUNYCODE, &val)))
+ mShowPunycode = val;
+ }
+ if (!pref || NS_LITERAL_STRING(NS_NET_PREF_IDNUSEWHITELIST).Equals(pref)) {
+ bool val;
+ if (NS_SUCCEEDED(prefBranch->GetBoolPref(NS_NET_PREF_IDNUSEWHITELIST,
+ &val)))
+ mIDNUseWhitelist = val;
+ }
+ if (!pref || NS_LITERAL_STRING(NS_NET_PREF_IDNRESTRICTION).Equals(pref)) {
+ nsXPIDLCString profile;
+ if (NS_FAILED(prefBranch->GetCharPref(NS_NET_PREF_IDNRESTRICTION,
+ getter_Copies(profile)))) {
+ profile.Truncate();
+ }
+ if (profile.EqualsLiteral("moderate")) {
+ mRestrictionProfile = eModeratelyRestrictiveProfile;
+ } else if (profile.EqualsLiteral("high")) {
+ mRestrictionProfile = eHighlyRestrictiveProfile;
+ } else {
+ mRestrictionProfile = eASCIIOnlyProfile;
+ }
+ }
+}
+
+nsIDNService::nsIDNService()
+ : mShowPunycode(false)
+ , mIDNUseWhitelist(false)
+{
+#ifdef IDNA2008
+ uint32_t IDNAOptions = UIDNA_CHECK_BIDI | UIDNA_CHECK_CONTEXTJ;
+ if (!kIDNA2008_TransitionalProcessing) {
+ IDNAOptions |= UIDNA_NONTRANSITIONAL_TO_UNICODE;
+ }
+ UErrorCode errorCode = U_ZERO_ERROR;
+ mIDNA = uidna_openUTS46(IDNAOptions, &errorCode);
+#else
+ if (idn_success != idn_nameprep_create(nullptr, &mNamePrepHandle))
+ mNamePrepHandle = nullptr;
+
+ mNormalizer = do_GetService(NS_UNICODE_NORMALIZER_CONTRACTID);
+ /* member initializers and constructor code */
+#endif
+}
+
+nsIDNService::~nsIDNService()
+{
+#ifdef IDNA2008
+ uidna_close(mIDNA);
+#else
+ idn_nameprep_destroy(mNamePrepHandle);
+#endif
+}
+
+#ifdef IDNA2008
+nsresult
+nsIDNService::IDNA2008ToUnicode(const nsACString& input, nsAString& output)
+{
+ NS_ConvertUTF8toUTF16 inputStr(input);
+ UIDNAInfo info = UIDNA_INFO_INITIALIZER;
+ UErrorCode errorCode = U_ZERO_ERROR;
+ int32_t inLen = inputStr.Length();
+ int32_t outMaxLen = kMaxDNSNodeLen + 1;
+ UChar outputBuffer[kMaxDNSNodeLen + 1];
+
+ int32_t outLen = uidna_labelToUnicode(mIDNA, (const UChar*)inputStr.get(),
+ inLen, outputBuffer, outMaxLen,
+ &info, &errorCode);
+ if (info.errors != 0) {
+ return NS_ERROR_MALFORMED_URI;
+ }
+
+ if (U_SUCCESS(errorCode)) {
+ ICUUtils::AssignUCharArrayToString(outputBuffer, outLen, output);
+ }
+
+ nsresult rv = ICUUtils::UErrorToNsResult(errorCode);
+ if (rv == NS_ERROR_FAILURE) {
+ rv = NS_ERROR_MALFORMED_URI;
+ }
+ return rv;
+}
+
+nsresult
+nsIDNService::IDNA2008StringPrep(const nsAString& input,
+ nsAString& output,
+ stringPrepFlag flag)
+{
+ UIDNAInfo info = UIDNA_INFO_INITIALIZER;
+ UErrorCode errorCode = U_ZERO_ERROR;
+ int32_t inLen = input.Length();
+ int32_t outMaxLen = kMaxDNSNodeLen + 1;
+ UChar outputBuffer[kMaxDNSNodeLen + 1];
+
+ int32_t outLen =
+ uidna_labelToUnicode(mIDNA, (const UChar*)PromiseFlatString(input).get(),
+ inLen, outputBuffer, outMaxLen, &info, &errorCode);
+ nsresult rv = ICUUtils::UErrorToNsResult(errorCode);
+ if (rv == NS_ERROR_FAILURE) {
+ rv = NS_ERROR_MALFORMED_URI;
+ }
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Output the result of nameToUnicode even if there were errors
+ ICUUtils::AssignUCharArrayToString(outputBuffer, outLen, output);
+
+ if (flag == eStringPrepIgnoreErrors) {
+ return NS_OK;
+ }
+
+ if (info.errors != 0) {
+ if (flag == eStringPrepForDNS) {
+ output.Truncate();
+ }
+ rv = NS_ERROR_MALFORMED_URI;
+ }
+
+ return rv;
+}
+#endif
+
+NS_IMETHODIMP nsIDNService::ConvertUTF8toACE(const nsACString & input, nsACString & ace)
+{
+ return UTF8toACE(input, ace, eStringPrepForDNS);
+}
+
+nsresult nsIDNService::UTF8toACE(const nsACString & input, nsACString & ace,
+ stringPrepFlag flag)
+{
+ nsresult rv;
+ NS_ConvertUTF8toUTF16 ustr(input);
+
+ // map ideographic period to ASCII period etc.
+ normalizeFullStops(ustr);
+
+ uint32_t len, offset;
+ len = 0;
+ offset = 0;
+ nsAutoCString encodedBuf;
+
+ nsAString::const_iterator start, end;
+ ustr.BeginReading(start);
+ ustr.EndReading(end);
+ ace.Truncate();
+
+ // encode nodes if non ASCII
+ while (start != end) {
+ len++;
+ if (*start++ == (char16_t)'.') {
+ rv = stringPrepAndACE(Substring(ustr, offset, len - 1), encodedBuf, flag);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ ace.Append(encodedBuf);
+ ace.Append('.');
+ offset += len;
+ len = 0;
+ }
+ }
+
+ // encode the last node if non ASCII
+ if (len) {
+ rv = stringPrepAndACE(Substring(ustr, offset, len), encodedBuf, flag);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ ace.Append(encodedBuf);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsIDNService::ConvertACEtoUTF8(const nsACString & input, nsACString & _retval)
+{
+ return ACEtoUTF8(input, _retval, eStringPrepForDNS);
+}
+
+nsresult nsIDNService::ACEtoUTF8(const nsACString & input, nsACString & _retval,
+ stringPrepFlag flag)
+{
+ // RFC 3490 - 4.2 ToUnicode
+ // ToUnicode never fails. If any step fails, then the original input
+ // sequence is returned immediately in that step.
+
+ uint32_t len = 0, offset = 0;
+ nsAutoCString decodedBuf;
+
+ nsACString::const_iterator start, end;
+ input.BeginReading(start);
+ input.EndReading(end);
+ _retval.Truncate();
+
+ // loop and decode nodes
+ while (start != end) {
+ len++;
+ if (*start++ == '.') {
+ if (NS_FAILED(decodeACE(Substring(input, offset, len - 1), decodedBuf,
+ flag))) {
+ _retval.Assign(input);
+ return NS_OK;
+ }
+
+ _retval.Append(decodedBuf);
+ _retval.Append('.');
+ offset += len;
+ len = 0;
+ }
+ }
+ // decode the last node
+ if (len) {
+ if (NS_FAILED(decodeACE(Substring(input, offset, len), decodedBuf,
+ flag)))
+ _retval.Assign(input);
+ else
+ _retval.Append(decodedBuf);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsIDNService::IsACE(const nsACString & input, bool *_retval)
+{
+ const char *data = input.BeginReading();
+ uint32_t dataLen = input.Length();
+
+ // look for the ACE prefix in the input string. it may occur
+ // at the beginning of any segment in the domain name. for
+ // example: "www.xn--ENCODED.com"
+
+ const char *p = PL_strncasestr(data, kACEPrefix, dataLen);
+
+ *_retval = p && (p == data || *(p - 1) == '.');
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsIDNService::Normalize(const nsACString & input,
+ nsACString & output)
+{
+ // protect against bogus input
+ NS_ENSURE_TRUE(IsUTF8(input), NS_ERROR_UNEXPECTED);
+
+ NS_ConvertUTF8toUTF16 inUTF16(input);
+ normalizeFullStops(inUTF16);
+
+ // pass the domain name to stringprep label by label
+ nsAutoString outUTF16, outLabel;
+
+ uint32_t len = 0, offset = 0;
+ nsresult rv;
+ nsAString::const_iterator start, end;
+ inUTF16.BeginReading(start);
+ inUTF16.EndReading(end);
+
+ while (start != end) {
+ len++;
+ if (*start++ == char16_t('.')) {
+ rv = stringPrep(Substring(inUTF16, offset, len - 1), outLabel,
+ eStringPrepIgnoreErrors);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ outUTF16.Append(outLabel);
+ outUTF16.Append(char16_t('.'));
+ offset += len;
+ len = 0;
+ }
+ }
+ if (len) {
+ rv = stringPrep(Substring(inUTF16, offset, len), outLabel,
+ eStringPrepIgnoreErrors);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ outUTF16.Append(outLabel);
+ }
+
+ CopyUTF16toUTF8(outUTF16, output);
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsIDNService::ConvertToDisplayIDN(const nsACString & input, bool * _isASCII, nsACString & _retval)
+{
+ // If host is ACE, then convert to UTF-8 if the host is in the IDN whitelist.
+ // Else, if host is already UTF-8, then make sure it is normalized per IDN.
+
+ nsresult rv = NS_OK;
+
+ // Even if the hostname is not ASCII, individual labels may still be ACE, so
+ // test IsACE before testing IsASCII
+ bool isACE;
+ IsACE(input, &isACE);
+
+ if (IsASCII(input)) {
+ // first, canonicalize the host to lowercase, for whitelist lookup
+ _retval = input;
+ ToLowerCase(_retval);
+
+ if (isACE && !mShowPunycode) {
+ // ACEtoUTF8() can't fail, but might return the original ACE string
+ nsAutoCString temp(_retval);
+ // If the domain is in the whitelist, return the host in UTF-8.
+ // Otherwise convert from ACE to UTF8 only those labels which are
+ // considered safe for display
+ ACEtoUTF8(temp, _retval, isInWhitelist(temp) ?
+ eStringPrepIgnoreErrors : eStringPrepForUI);
+ *_isASCII = IsASCII(_retval);
+ } else {
+ *_isASCII = true;
+ }
+ } else {
+ // We have to normalize the hostname before testing against the domain
+ // whitelist (see bug 315411), and to ensure the entire string gets
+ // normalized.
+ //
+ // Normalization and the tests for safe display below, assume that the
+ // input is Unicode, so first convert any ACE labels to UTF8
+ if (isACE) {
+ nsAutoCString temp;
+ ACEtoUTF8(input, temp, eStringPrepIgnoreErrors);
+ rv = Normalize(temp, _retval);
+ } else {
+ rv = Normalize(input, _retval);
+ }
+ if (NS_FAILED(rv)) return rv;
+
+ if (mShowPunycode && NS_SUCCEEDED(UTF8toACE(_retval, _retval,
+ eStringPrepIgnoreErrors))) {
+ *_isASCII = true;
+ return NS_OK;
+ }
+
+ // normalization could result in an ASCII-only hostname. alternatively, if
+ // the host is converted to ACE by the normalizer, then the host may contain
+ // unsafe characters, so leave it ACE encoded. see bug 283016, bug 301694, and bug 309311.
+ *_isASCII = IsASCII(_retval);
+ if (!*_isASCII && !isInWhitelist(_retval)) {
+ // UTF8toACE with eStringPrepForUI may return a domain name where
+ // some labels are in UTF-8 and some are in ACE, depending on
+ // whether they are considered safe for display
+ rv = UTF8toACE(_retval, _retval, eStringPrepForUI);
+ *_isASCII = IsASCII(_retval);
+ return rv;
+ }
+ }
+
+ return NS_OK;
+}
+
+//-----------------------------------------------------------------------------
+
+static nsresult utf16ToUcs4(const nsAString& in,
+ uint32_t *out,
+ uint32_t outBufLen,
+ uint32_t *outLen)
+{
+ uint32_t i = 0;
+ nsAString::const_iterator start, end;
+ in.BeginReading(start);
+ in.EndReading(end);
+
+ while (start != end) {
+ char16_t curChar;
+
+ curChar= *start++;
+
+ if (start != end &&
+ NS_IS_HIGH_SURROGATE(curChar) &&
+ NS_IS_LOW_SURROGATE(*start)) {
+ out[i] = SURROGATE_TO_UCS4(curChar, *start);
+ ++start;
+ }
+ else
+ out[i] = curChar;
+
+ i++;
+ if (i >= outBufLen)
+ return NS_ERROR_MALFORMED_URI;
+ }
+ out[i] = (uint32_t)'\0';
+ *outLen = i;
+ return NS_OK;
+}
+
+#ifndef IDNA2008
+static void ucs4toUtf16(const uint32_t *in, nsAString& out)
+{
+ while (*in) {
+ if (!IS_IN_BMP(*in)) {
+ out.Append((char16_t) H_SURROGATE(*in));
+ out.Append((char16_t) L_SURROGATE(*in));
+ }
+ else
+ out.Append((char16_t) *in);
+ in++;
+ }
+}
+#endif
+
+static nsresult punycode(const nsAString& in, nsACString& out)
+{
+ uint32_t ucs4Buf[kMaxDNSNodeLen + 1];
+ uint32_t ucs4Len = 0u;
+ nsresult rv = utf16ToUcs4(in, ucs4Buf, kMaxDNSNodeLen, &ucs4Len);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // need maximum 20 bits to encode 16 bit Unicode character
+ // (include null terminator)
+ const uint32_t kEncodedBufSize = kMaxDNSNodeLen * 20 / 8 + 1 + 1;
+ char encodedBuf[kEncodedBufSize];
+ punycode_uint encodedLength = kEncodedBufSize;
+
+ enum punycode_status status = punycode_encode(ucs4Len,
+ ucs4Buf,
+ nullptr,
+ &encodedLength,
+ encodedBuf);
+
+ if (punycode_success != status ||
+ encodedLength >= kEncodedBufSize)
+ return NS_ERROR_MALFORMED_URI;
+
+ encodedBuf[encodedLength] = '\0';
+ out.Assign(nsDependentCString(kACEPrefix) + nsDependentCString(encodedBuf));
+
+ return rv;
+}
+
+// RFC 3454
+//
+// 1) Map -- For each character in the input, check if it has a mapping
+// and, if so, replace it with its mapping. This is described in section 3.
+//
+// 2) Normalize -- Possibly normalize the result of step 1 using Unicode
+// normalization. This is described in section 4.
+//
+// 3) Prohibit -- Check for any characters that are not allowed in the
+// output. If any are found, return an error. This is described in section
+// 5.
+//
+// 4) Check bidi -- Possibly check for right-to-left characters, and if any
+// are found, make sure that the whole string satisfies the requirements
+// for bidirectional strings. If the string does not satisfy the requirements
+// for bidirectional strings, return an error. This is described in section 6.
+//
+// 5) Check unassigned code points -- If allowUnassigned is false, check for
+// any unassigned Unicode points and if any are found return an error.
+// This is described in section 7.
+//
+nsresult nsIDNService::stringPrep(const nsAString& in, nsAString& out,
+ stringPrepFlag flag)
+{
+#ifdef IDNA2008
+ return IDNA2008StringPrep(in, out, flag);
+#else
+ if (!mNamePrepHandle || !mNormalizer)
+ return NS_ERROR_FAILURE;
+
+ uint32_t ucs4Buf[kMaxDNSNodeLen + 1];
+ uint32_t ucs4Len;
+ nsresult rv = utf16ToUcs4(in, ucs4Buf, kMaxDNSNodeLen, &ucs4Len);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // map
+ idn_result_t idn_err;
+
+ uint32_t namePrepBuf[kMaxDNSNodeLen * 3]; // map up to three characters
+ idn_err = idn_nameprep_map(mNamePrepHandle, (const uint32_t *) ucs4Buf,
+ (uint32_t *) namePrepBuf, kMaxDNSNodeLen * 3);
+ NS_ENSURE_TRUE(idn_err == idn_success, NS_ERROR_MALFORMED_URI);
+
+ nsAutoString namePrepStr;
+ ucs4toUtf16(namePrepBuf, namePrepStr);
+ if (namePrepStr.Length() >= kMaxDNSNodeLen)
+ return NS_ERROR_MALFORMED_URI;
+
+ // normalize
+ nsAutoString normlizedStr;
+ rv = mNormalizer->NormalizeUnicodeNFKC(namePrepStr, normlizedStr);
+ if (normlizedStr.Length() >= kMaxDNSNodeLen)
+ return NS_ERROR_MALFORMED_URI;
+
+ // set the result string
+ out.Assign(normlizedStr);
+
+ if (flag == eStringPrepIgnoreErrors) {
+ return NS_OK;
+ }
+
+ // prohibit
+ const uint32_t *found = nullptr;
+ idn_err = idn_nameprep_isprohibited(mNamePrepHandle,
+ (const uint32_t *) ucs4Buf, &found);
+ if (idn_err != idn_success || found) {
+ rv = NS_ERROR_MALFORMED_URI;
+ } else {
+ // check bidi
+ idn_err = idn_nameprep_isvalidbidi(mNamePrepHandle,
+ (const uint32_t *) ucs4Buf, &found);
+ if (idn_err != idn_success || found) {
+ rv = NS_ERROR_MALFORMED_URI;
+ } else if (flag == eStringPrepForUI) {
+ // check unassigned code points
+ idn_err = idn_nameprep_isunassigned(mNamePrepHandle,
+ (const uint32_t *) ucs4Buf, &found);
+ if (idn_err != idn_success || found) {
+ rv = NS_ERROR_MALFORMED_URI;
+ }
+ }
+ }
+
+ if (flag == eStringPrepForDNS && NS_FAILED(rv)) {
+ out.Truncate();
+ }
+
+ return rv;
+#endif
+}
+
+nsresult nsIDNService::stringPrepAndACE(const nsAString& in, nsACString& out,
+ stringPrepFlag flag)
+{
+ nsresult rv = NS_OK;
+
+ out.Truncate();
+
+ if (in.Length() > kMaxDNSNodeLen) {
+ NS_WARNING("IDN node too large");
+ return NS_ERROR_MALFORMED_URI;
+ }
+
+ if (IsASCII(in)) {
+ LossyCopyUTF16toASCII(in, out);
+ return NS_OK;
+ }
+
+ nsAutoString strPrep;
+ rv = stringPrep(in, strPrep, flag);
+ if (flag == eStringPrepForDNS) {
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ if (IsASCII(strPrep)) {
+ LossyCopyUTF16toASCII(strPrep, out);
+ return NS_OK;
+ }
+
+ if (flag == eStringPrepForUI && NS_SUCCEEDED(rv) && isLabelSafe(in)) {
+ CopyUTF16toUTF8(strPrep, out);
+ return NS_OK;
+ }
+
+ rv = punycode(strPrep, out);
+ // Check that the encoded output isn't larger than the maximum length
+ // of a DNS node per RFC 1034.
+ // This test isn't necessary in the code paths above where the input
+ // is ASCII (since the output will be the same length as the input) or
+ // where we convert to UTF-8 (since the output is only used for
+ // display in the UI and not passed to DNS and can legitimately be
+ // longer than the limit).
+ if (out.Length() > kMaxDNSNodeLen) {
+ NS_WARNING("IDN node too large");
+ return NS_ERROR_MALFORMED_URI;
+ }
+
+ return rv;
+}
+
+// RFC 3490
+// 1) Whenever dots are used as label separators, the following characters
+// MUST be recognized as dots: U+002E (full stop), U+3002 (ideographic full
+// stop), U+FF0E (fullwidth full stop), U+FF61 (halfwidth ideographic full
+// stop).
+
+void nsIDNService::normalizeFullStops(nsAString& s)
+{
+ nsAString::const_iterator start, end;
+ s.BeginReading(start);
+ s.EndReading(end);
+ int32_t index = 0;
+
+ while (start != end) {
+ switch (*start) {
+ case 0x3002:
+ case 0xFF0E:
+ case 0xFF61:
+ s.Replace(index, 1, NS_LITERAL_STRING("."));
+ break;
+ default:
+ break;
+ }
+ start++;
+ index++;
+ }
+}
+
+nsresult nsIDNService::decodeACE(const nsACString& in, nsACString& out,
+ stringPrepFlag flag)
+{
+ bool isAce;
+ IsACE(in, &isAce);
+ if (!isAce) {
+ out.Assign(in);
+ return NS_OK;
+ }
+
+ nsAutoString utf16;
+#ifdef IDNA2008
+ nsresult result = IDNA2008ToUnicode(in, utf16);
+ NS_ENSURE_SUCCESS(result, result);
+#else
+ // RFC 3490 - 4.2 ToUnicode
+ // The ToUnicode output never contains more code points than its input.
+ punycode_uint output_length = in.Length() - kACEPrefixLen + 1;
+ auto *output = new punycode_uint[output_length];
+ NS_ENSURE_TRUE(output, NS_ERROR_OUT_OF_MEMORY);
+
+ enum punycode_status status = punycode_decode(in.Length() - kACEPrefixLen,
+ PromiseFlatCString(in).get() + kACEPrefixLen,
+ &output_length,
+ output,
+ nullptr);
+ if (status != punycode_success) {
+ delete [] output;
+ return NS_ERROR_MALFORMED_URI;
+ }
+
+ // UCS4 -> UTF8
+ output[output_length] = 0;
+ ucs4toUtf16(output, utf16);
+ delete [] output;
+#endif
+ if (flag != eStringPrepForUI || isLabelSafe(utf16)) {
+ CopyUTF16toUTF8(utf16, out);
+ } else {
+ out.Assign(in);
+ return NS_OK;
+ }
+
+ // Validation: encode back to ACE and compare the strings
+ nsAutoCString ace;
+ nsresult rv = UTF8toACE(out, ace, flag);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (flag == eStringPrepForDNS &&
+ !ace.Equals(in, nsCaseInsensitiveCStringComparator())) {
+ return NS_ERROR_MALFORMED_URI;
+ }
+
+ return NS_OK;
+}
+
+bool nsIDNService::isInWhitelist(const nsACString &host)
+{
+ if (mIDNUseWhitelist && mIDNWhitelistPrefBranch) {
+ nsAutoCString tld(host);
+ // make sure the host is ACE for lookup and check that there are no
+ // unassigned codepoints
+ if (!IsASCII(tld) && NS_FAILED(UTF8toACE(tld, tld, eStringPrepForDNS))) {
+ return false;
+ }
+
+ // truncate trailing dots first
+ tld.Trim(".");
+ int32_t pos = tld.RFind(".");
+ if (pos == kNotFound)
+ return false;
+
+ tld.Cut(0, pos + 1);
+
+ bool safe;
+ if (NS_SUCCEEDED(mIDNWhitelistPrefBranch->GetBoolPref(tld.get(), &safe)))
+ return safe;
+ }
+
+ return false;
+}
+
+bool nsIDNService::isLabelSafe(const nsAString &label)
+{
+ if (!isOnlySafeChars(PromiseFlatString(label), mIDNBlacklist)) {
+ return false;
+ }
+
+ // We should never get here if the label is ASCII
+ NS_ASSERTION(!IsASCII(label), "ASCII label in IDN checking");
+ if (mRestrictionProfile == eASCIIOnlyProfile) {
+ return false;
+ }
+
+ nsAString::const_iterator current, end;
+ label.BeginReading(current);
+ label.EndReading(end);
+
+ Script lastScript = Script::INVALID;
+ uint32_t previousChar = 0;
+ uint32_t savedNumberingSystem = 0;
+// Simplified/Traditional Chinese check temporarily disabled -- bug 857481
+#if 0
+ HanVariantType savedHanVariant = HVT_NotHan;
+#endif
+
+ int32_t savedScript = -1;
+
+ while (current != end) {
+ uint32_t ch = *current++;
+
+ if (NS_IS_HIGH_SURROGATE(ch) && current != end &&
+ NS_IS_LOW_SURROGATE(*current)) {
+ ch = SURROGATE_TO_UCS4(ch, *current++);
+ }
+
+ // Check for restricted characters; aspirational scripts are NOT permitted,
+ // in anticipation of the category being merged into Limited-Use scripts
+ // in the upcoming (Unicode 10.0-based) revision of UAX #31.
+ XidmodType xm = GetIdentifierModification(ch);
+ if (xm != XIDMOD_RECOMMENDED &&
+ xm != XIDMOD_INCLUSION) {
+ return false;
+ }
+
+ // Check for mixed script
+ Script script = GetScriptCode(ch);
+ if (script != Script::COMMON &&
+ script != Script::INHERITED &&
+ script != lastScript) {
+ if (illegalScriptCombo(script, savedScript)) {
+ return false;
+ }
+ lastScript = script;
+ }
+
+ // Check for mixed numbering systems
+ if (GetGeneralCategory(ch) ==
+ HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) {
+ uint32_t zeroCharacter = ch - GetNumericValue(ch);
+ if (savedNumberingSystem == 0) {
+ // If we encounter a decimal number, save the zero character from that
+ // numbering system.
+ savedNumberingSystem = zeroCharacter;
+ } else if (zeroCharacter != savedNumberingSystem) {
+ return false;
+ }
+ }
+
+ // Check for consecutive non-spacing marks
+ if (previousChar != 0 &&
+ previousChar == ch &&
+ GetGeneralCategory(ch) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) {
+ return false;
+ }
+
+ // Simplified/Traditional Chinese check temporarily disabled -- bug 857481
+#if 0
+
+ // Check for both simplified-only and traditional-only Chinese characters
+ HanVariantType hanVariant = GetHanVariant(ch);
+ if (hanVariant == HVT_SimplifiedOnly || hanVariant == HVT_TraditionalOnly) {
+ if (savedHanVariant == HVT_NotHan) {
+ savedHanVariant = hanVariant;
+ } else if (hanVariant != savedHanVariant) {
+ return false;
+ }
+ }
+#endif
+
+ previousChar = ch;
+ }
+ return true;
+}
+
+// Scripts that we care about in illegalScriptCombo
+static const Script scriptTable[] = {
+ Script::BOPOMOFO, Script::CYRILLIC, Script::GREEK,
+ Script::HANGUL, Script::HAN, Script::HIRAGANA,
+ Script::KATAKANA, Script::LATIN };
+
+#define BOPO 0
+#define CYRL 1
+#define GREK 2
+#define HANG 3
+#define HANI 4
+#define HIRA 5
+#define KATA 6
+#define LATN 7
+#define OTHR 8
+#define JPAN 9 // Latin + Han + Hiragana + Katakana
+#define CHNA 10 // Latin + Han + Bopomofo
+#define KORE 11 // Latin + Han + Hangul
+#define HNLT 12 // Latin + Han (could be any of the above combinations)
+#define FAIL 13
+
+static inline int32_t findScriptIndex(Script aScript)
+{
+ int32_t tableLength = sizeof(scriptTable) / sizeof(int32_t);
+ for (int32_t index = 0; index < tableLength; ++index) {
+ if (aScript == scriptTable[index]) {
+ return index;
+ }
+ }
+ return OTHR;
+}
+
+static const int32_t scriptComboTable[13][9] = {
+/* thisScript: BOPO CYRL GREK HANG HANI HIRA KATA LATN OTHR
+ * savedScript */
+ /* BOPO */ { BOPO, FAIL, FAIL, FAIL, CHNA, FAIL, FAIL, CHNA, FAIL },
+ /* CYRL */ { FAIL, CYRL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL },
+ /* GREK */ { FAIL, FAIL, GREK, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL },
+ /* HANG */ { FAIL, FAIL, FAIL, HANG, KORE, FAIL, FAIL, KORE, FAIL },
+ /* HANI */ { CHNA, FAIL, FAIL, KORE, HANI, JPAN, JPAN, HNLT, FAIL },
+ /* HIRA */ { FAIL, FAIL, FAIL, FAIL, JPAN, HIRA, JPAN, JPAN, FAIL },
+ /* KATA */ { FAIL, FAIL, FAIL, FAIL, JPAN, JPAN, KATA, JPAN, FAIL },
+ /* LATN */ { CHNA, FAIL, FAIL, KORE, HNLT, JPAN, JPAN, LATN, OTHR },
+ /* OTHR */ { FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, OTHR, FAIL },
+ /* JPAN */ { FAIL, FAIL, FAIL, FAIL, JPAN, JPAN, JPAN, JPAN, FAIL },
+ /* CHNA */ { CHNA, FAIL, FAIL, FAIL, CHNA, FAIL, FAIL, CHNA, FAIL },
+ /* KORE */ { FAIL, FAIL, FAIL, KORE, KORE, FAIL, FAIL, KORE, FAIL },
+ /* HNLT */ { CHNA, FAIL, FAIL, KORE, HNLT, JPAN, JPAN, HNLT, FAIL }
+};
+
+bool nsIDNService::illegalScriptCombo(Script script, int32_t& savedScript)
+{
+ if (savedScript == -1) {
+ savedScript = findScriptIndex(script);
+ return false;
+ }
+
+ savedScript = scriptComboTable[savedScript] [findScriptIndex(script)];
+ /*
+ * Special case combinations that depend on which profile is in use
+ * In the Highly Restrictive profile Latin is not allowed with any
+ * other script
+ *
+ * In the Moderately Restrictive profile Latin mixed with any other
+ * single script is allowed.
+ */
+ return ((savedScript == OTHR &&
+ mRestrictionProfile == eHighlyRestrictiveProfile) ||
+ savedScript == FAIL);
+}
+
+#undef BOPO
+#undef CYRL
+#undef GREK
+#undef HANG
+#undef HANI
+#undef HIRA
+#undef KATA
+#undef LATN
+#undef OTHR
+#undef JPAN
+#undef CHNA
+#undef KORE
+#undef HNLT
+#undef FAIL
diff --git a/netwerk/dns/nsIDNService.h b/netwerk/dns/nsIDNService.h
new file mode 100644
index 000000000..19aa94da0
--- /dev/null
+++ b/netwerk/dns/nsIDNService.h
@@ -0,0 +1,195 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsIDNService_h__
+#define nsIDNService_h__
+
+#include "nsIIDNService.h"
+#include "nsCOMPtr.h"
+#include "nsIObserver.h"
+#include "nsUnicodeScriptCodes.h"
+#include "nsWeakReference.h"
+
+#ifdef IDNA2008
+#include "unicode/uidna.h"
+#else
+#include "nsIUnicodeNormalizer.h"
+#include "nsIDNKitInterface.h"
+#endif
+
+#include "nsString.h"
+
+class nsIPrefBranch;
+
+//-----------------------------------------------------------------------------
+// nsIDNService
+//-----------------------------------------------------------------------------
+
+class nsIDNService final : public nsIIDNService,
+ public nsIObserver,
+ public nsSupportsWeakReference
+{
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIIDNSERVICE
+ NS_DECL_NSIOBSERVER
+
+ nsIDNService();
+
+ nsresult Init();
+
+protected:
+ virtual ~nsIDNService();
+
+private:
+ enum stringPrepFlag {
+ eStringPrepForDNS,
+ eStringPrepForUI,
+ eStringPrepIgnoreErrors
+ };
+
+ /**
+ * Convert the following characters that must be recognized as label
+ * separators per RFC 3490 to ASCII full stop characters
+ *
+ * U+3002 (ideographic full stop)
+ * U+FF0E (fullwidth full stop)
+ * U+FF61 (halfwidth ideographic full stop)
+ */
+ void normalizeFullStops(nsAString& s);
+
+ /**
+ * Convert and encode a DNS label in ACE/punycode.
+ * @param flag
+ * if eStringPrepIgnoreErrors, all non-ASCII labels are
+ * converted to punycode.
+ * if eStringPrepForUI, only labels that are considered safe
+ * for display are converted.
+ * @see isLabelSafe
+ * if eStringPrepForDNS and stringPrep finds an illegal
+ * character, returns NS_FAILURE and out is empty
+ */
+ nsresult stringPrepAndACE(const nsAString& in, nsACString& out,
+ stringPrepFlag flag);
+
+ /**
+ * Convert a DNS label using the stringprep profile defined in RFC 3454
+ */
+ nsresult stringPrep(const nsAString& in, nsAString& out, stringPrepFlag flag);
+
+ /**
+ * Decode an ACE-encoded DNS label to UTF-8
+ *
+ * @param flag
+ * if eStringPrepForUI and the label is not considered safe to
+ * display, the output is the same as the input
+ * @see isLabelSafe
+ */
+ nsresult decodeACE(const nsACString& in, nsACString& out,
+ stringPrepFlag flag);
+
+ /**
+ * Convert complete domain names between UTF8 and ACE and vice versa
+ *
+ * @param flag is passed to decodeACE or stringPrepAndACE for each
+ * label individually, so the output may contain some labels in
+ * punycode and some in UTF-8
+ */
+ nsresult UTF8toACE(const nsACString& input, nsACString& ace,
+ stringPrepFlag flag);
+ nsresult ACEtoUTF8(const nsACString& input, nsACString& _retval,
+ stringPrepFlag flag);
+
+ bool isInWhitelist(const nsACString &host);
+ void prefsChanged(nsIPrefBranch *prefBranch, const char16_t *pref);
+
+ /**
+ * Determine whether a label is considered safe to display to the user
+ * according to the algorithm defined in UTR 39 and the profile
+ * selected in mRestrictionProfile.
+ *
+ * For the ASCII-only profile, returns false for all labels containing
+ * non-ASCII characters.
+ *
+ * For the other profiles, returns false for labels containing any of
+ * the following:
+ *
+ * Characters in scripts other than the "recommended scripts" and
+ * "aspirational scripts" defined in
+ * http://www.unicode.org/reports/tr31/#Table_Recommended_Scripts
+ * and http://www.unicode.org/reports/tr31/#Aspirational_Use_Scripts
+ * This includes codepoints that are not defined as Unicode
+ * characters
+ *
+ * Illegal combinations of scripts (@see illegalScriptCombo)
+ *
+ * Numbers from more than one different numbering system
+ *
+ * Sequences of the same non-spacing mark
+ *
+ * Both simplified-only and traditional-only Chinese characters
+ * XXX this test was disabled by bug 857481
+ */
+ bool isLabelSafe(const nsAString &label);
+
+ /**
+ * Determine whether a combination of scripts in a single label is
+ * permitted according to the algorithm defined in UTR 39 and the
+ * profile selected in mRestrictionProfile.
+ *
+ * For the "Highly restrictive" profile, all characters in each
+ * identifier must be from a single script, or from the combinations:
+ * Latin + Han + Hiragana + Katakana;
+ * Latin + Han + Bopomofo; or
+ * Latin + Han + Hangul
+ *
+ * For the "Moderately restrictive" profile, Latin is also allowed
+ * with other scripts except Cyrillic and Greek
+ */
+ bool illegalScriptCombo(mozilla::unicode::Script script,
+ int32_t& savedScript);
+
+#ifdef IDNA2008
+ /**
+ * Convert a DNS label from ASCII to Unicode using IDNA2008
+ */
+ nsresult IDNA2008ToUnicode(const nsACString& input, nsAString& output);
+
+ /**
+ * Convert a DNS label to a normalized form conforming to IDNA2008
+ */
+ nsresult IDNA2008StringPrep(const nsAString& input, nsAString& output,
+ stringPrepFlag flag);
+
+ UIDNA* mIDNA;
+#else
+ idn_nameprep_t mNamePrepHandle;
+ nsCOMPtr<nsIUnicodeNormalizer> mNormalizer;
+#endif
+ nsXPIDLString mIDNBlacklist;
+
+ /**
+ * Flag set by the pref network.IDN_show_punycode. When it is true,
+ * IDNs containing non-ASCII characters are always displayed to the
+ * user in punycode
+ */
+ bool mShowPunycode;
+
+ /**
+ * Restriction-level Detection profiles defined in UTR 39
+ * http://www.unicode.org/reports/tr39/#Restriction_Level_Detection,
+ * and selected by the pref network.IDN.restriction_profile
+ */
+ enum restrictionProfile {
+ eASCIIOnlyProfile,
+ eHighlyRestrictiveProfile,
+ eModeratelyRestrictiveProfile
+ };
+ restrictionProfile mRestrictionProfile;
+ nsCOMPtr<nsIPrefBranch> mIDNWhitelistPrefBranch;
+ bool mIDNUseWhitelist;
+};
+
+#endif // nsIDNService_h__
diff --git a/netwerk/dns/nsIEffectiveTLDService.idl b/netwerk/dns/nsIEffectiveTLDService.idl
new file mode 100644
index 000000000..adfbae8a0
--- /dev/null
+++ b/netwerk/dns/nsIEffectiveTLDService.idl
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+interface nsIURI;
+
+[scriptable, uuid(68067eb5-ad8d-43cb-a043-1cc85ebe06e7)]
+interface nsIEffectiveTLDService : nsISupports
+{
+ /**
+ * Returns the public suffix of a URI. A public suffix is the highest-level domain
+ * under which individual domains may be registered; it may therefore contain one
+ * or more dots. For example, the public suffix for "www.bbc.co.uk" is "co.uk",
+ * because the .uk TLD does not allow the registration of domains at the
+ * second level ("bbc.uk" is forbidden).
+ *
+ * The public suffix will be returned encoded in ASCII/ACE and will be normalized
+ * according to RFC 3454, i.e. the same encoding returned by nsIURI::GetAsciiHost().
+ * If consumers wish to compare the result of this method against the host from
+ * another nsIURI, the host should be obtained using nsIURI::GetAsciiHost().
+ * In the case of nested URIs, the innermost URI will be used.
+ *
+ * @param aURI The URI to be analyzed
+ *
+ * @returns the public suffix
+ *
+ * @throws NS_ERROR_UNEXPECTED
+ * or other error returned by nsIIDNService::normalize when
+ * the hostname contains characters disallowed in URIs
+ * @throws NS_ERROR_HOST_IS_IP_ADDRESS
+ * if the host is a numeric IPv4 or IPv6 address (as determined by
+ * the success of a call to PR_StringToNetAddr()).
+ */
+ ACString getPublicSuffix(in nsIURI aURI);
+
+ /**
+ * Returns the base domain of a URI; that is, the public suffix with a given
+ * number of additional domain name parts. For example, the result of this method
+ * for "www.bbc.co.uk", depending on the value of aAdditionalParts parameter, will
+ * be:
+ *
+ * 0 (default) -> bbc.co.uk
+ * 1 -> www.bbc.co.uk
+ *
+ * Similarly, the public suffix for "www.developer.mozilla.org" is "org", and the base
+ * domain will be:
+ *
+ * 0 (default) -> mozilla.org
+ * 1 -> developer.mozilla.org
+ * 2 -> www.developer.mozilla.org
+ *
+ * The base domain will be returned encoded in ASCII/ACE and will be normalized
+ * according to RFC 3454, i.e. the same encoding returned by nsIURI::GetAsciiHost().
+ * If consumers wish to compare the result of this method against the host from
+ * another nsIURI, the host should be obtained using nsIURI::GetAsciiHost().
+ * In the case of nested URIs, the innermost URI will be used.
+ *
+ * @param aURI The URI to be analyzed
+ * @param aAdditionalParts Number of domain name parts to be
+ * returned in addition to the public suffix
+ *
+ * @returns the base domain (public suffix plus the requested number of additional parts)
+ *
+ * @throws NS_ERROR_UNEXPECTED
+ * or other error returned by nsIIDNService::normalize when
+ * the hostname contains characters disallowed in URIs
+ * @throws NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS
+ * when there are insufficient subdomain levels in the hostname to satisfy the
+ * requested aAdditionalParts value.
+ * @throws NS_ERROR_HOST_IS_IP_ADDRESS
+ * if aHost is a numeric IPv4 or IPv6 address (as determined by
+ * the success of a call to PR_StringToNetAddr()).
+ *
+ * @see getPublicSuffix()
+ */
+ ACString getBaseDomain(in nsIURI aURI, [optional] in uint32_t aAdditionalParts);
+
+ /**
+ * NOTE: It is strongly recommended to use getPublicSuffix() above if a suitable
+ * nsIURI is available. Only use this method if this is not the case.
+ *
+ * Returns the public suffix of a host string. Otherwise identical to getPublicSuffix().
+ *
+ * @param aHost The host to be analyzed. Any additional parts (e.g. scheme,
+ * port, or path) will cause this method to throw. ASCII/ACE and
+ * UTF8 encodings are acceptable as input; normalization will
+ * be performed as specified in getBaseDomain().
+ *
+ * @see getPublicSuffix()
+ */
+ ACString getPublicSuffixFromHost(in AUTF8String aHost);
+
+ /**
+ * NOTE: It is strongly recommended to use getBaseDomain() above if a suitable
+ * nsIURI is available. Only use this method if this is not the case.
+ *
+ * Returns the base domain of a host string. Otherwise identical to getBaseDomain().
+ *
+ * @param aHost The host to be analyzed. Any additional parts (e.g. scheme,
+ * port, or path) will cause this method to throw. ASCII/ACE and
+ * UTF8 encodings are acceptable as input; normalization will
+ * be performed as specified in getBaseDomain().
+ *
+ * @see getBaseDomain()
+ */
+ ACString getBaseDomainFromHost(in AUTF8String aHost, [optional] in uint32_t aAdditionalParts);
+
+ /**
+ * Returns the parent sub-domain of a host string. If the host is a base
+ * domain, it will throw NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS.
+ *
+ * For example: "player.bbc.co.uk" would return "bbc.co.uk" and
+ * "bbc.co.uk" would throw NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS.
+ *
+ * @param aHost The host to be analyzed. Any additional parts (e.g. scheme,
+ * port, or path) will cause this method to throw. ASCII/ACE and
+ * UTF8 encodings are acceptable as input; normalization will
+ * be performed as specified in getBaseDomain().
+ */
+ ACString getNextSubDomain(in AUTF8String aHost);
+};
+
diff --git a/netwerk/dns/nsIIDNService.idl b/netwerk/dns/nsIIDNService.idl
new file mode 100644
index 000000000..47ef56123
--- /dev/null
+++ b/netwerk/dns/nsIIDNService.idl
@@ -0,0 +1,58 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+/**
+ * nsIIDNService interface.
+ *
+ * IDN (Internationalized Domain Name) support. Provides facilities
+ * for manipulating IDN hostnames according to the specification set
+ * forth by the IETF.
+ *
+ * IDN effort:
+ * http://www.ietf.org/html.characters/idn-charter.html
+ * http://www.i-dns.net
+ *
+ * IDNA specification:
+ * http://search.ietf.org/internet-drafts/draft-ietf-idn-idna-06.txt
+ */
+
+[scriptable, uuid(a592a60e-3621-4f19-a318-2bf233cfad3e)]
+interface nsIIDNService : nsISupports
+{
+ /**
+ * Prepares the input hostname according to IDNA ToASCII operation,
+ * the input hostname is assumed to be UTF8-encoded.
+ */
+ ACString convertUTF8toACE(in AUTF8String input);
+
+
+ /**
+ * This is the ToUnicode operation as specified in the IDNA proposal,
+ * with an additional step to encode the result in UTF-8.
+ * It takes an ACE-encoded hostname and performs ToUnicode to it, then
+ * encodes the resulting string into UTF8.
+ */
+ AUTF8String convertACEtoUTF8(in ACString input);
+
+ /**
+ * Checks if the input string is ACE encoded or not.
+ */
+ boolean isACE(in ACString input);
+
+ /**
+ * Performs the unicode normalization needed for hostnames in IDN,
+ * for callers that want early normalization.
+ */
+ AUTF8String normalize(in AUTF8String input);
+
+ /**
+ * Normalizes and converts a host to UTF-8 if the host is in the IDN
+ * whitelist, otherwise converts it to ACE. This is useful for display
+ * purposes and to ensure an encoding consistent with nsIURI::GetHost().
+ * If the result is ASCII or ACE encoded, |isASCII| will be true.
+ */
+ AUTF8String convertToDisplayIDN(in AUTF8String input, out boolean isASCII);
+};
diff --git a/netwerk/dns/nsPIDNSService.idl b/netwerk/dns/nsPIDNSService.idl
new file mode 100644
index 000000000..9bed0555c
--- /dev/null
+++ b/netwerk/dns/nsPIDNSService.idl
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIDNSService.idl"
+
+/**
+ * This is a private interface used by the internals of the networking library.
+ * It will never be frozen. Do not use it in external code.
+ */
+[scriptable, uuid(24e598fd-7b1a-436c-9154-14d8b38df8a5)]
+interface nsPIDNSService : nsIDNSService
+{
+ /**
+ * called to initialize the DNS service.
+ */
+ void init();
+
+ /**
+ * called to shutdown the DNS service. any pending asynchronous
+ * requests will be canceled, and the local cache of DNS records
+ * will be cleared. NOTE: the operating system may still have
+ * its own cache of DNS records, which would be unaffected by
+ * this method.
+ */
+ void shutdown();
+
+ /**
+ * Whether or not DNS prefetching (aka RESOLVE_SPECULATE) is enabled
+ */
+ attribute boolean prefetchEnabled;
+};
diff --git a/netwerk/dns/prepare_tlds.py b/netwerk/dns/prepare_tlds.py
new file mode 100644
index 000000000..a97b20948
--- /dev/null
+++ b/netwerk/dns/prepare_tlds.py
@@ -0,0 +1,121 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import codecs
+import encodings.idna
+import re
+import sys
+
+"""
+Processes a file containing effective TLD data. See the following URL for a
+description of effective TLDs and of the file format that this script
+processes (although for the latter you're better off just reading this file's
+short source code).
+
+http://wiki.mozilla.org/Gecko:Effective_TLD_Service
+"""
+
+def getEffectiveTLDs(path):
+ file = codecs.open(path, "r", "UTF-8")
+ entries = []
+ domains = set()
+ for line in file:
+ # line always contains a line terminator unless the file is empty
+ if len(line) == 0:
+ raise StopIteration
+ line = line.rstrip()
+ # comment, empty, or superfluous line for explicitness purposes
+ if line.startswith("//") or "." not in line:
+ continue
+ line = re.split(r"[ \t\n]", line, 1)[0]
+ entry = EffectiveTLDEntry(line)
+ domain = entry.domain()
+ assert domain not in domains, \
+ "repeating domain %s makes no sense" % domain
+ domains.add(domain)
+ entries.append(entry)
+
+ # Sort the entries so we can use binary search on them.
+ entries.sort(key=EffectiveTLDEntry.domain)
+
+ return entries
+
+def _normalizeHostname(domain):
+ """
+ Normalizes the given domain, component by component. ASCII components are
+ lowercased, while non-ASCII components are processed using the ToASCII
+ algorithm.
+ """
+ def convertLabel(label):
+ if _isASCII(label):
+ return label.lower()
+ return encodings.idna.ToASCII(label)
+ return ".".join(map(convertLabel, domain.split(".")))
+
+def _isASCII(s):
+ "True if s consists entirely of ASCII characters, false otherwise."
+ for c in s:
+ if ord(c) > 127:
+ return False
+ return True
+
+class EffectiveTLDEntry:
+ """
+ Stores an entry in an effective-TLD name file.
+ """
+
+ _exception = False
+ _wild = False
+
+ def __init__(self, line):
+ """
+ Creates a TLD entry from a line of data, which must have been stripped of
+ the line ending.
+ """
+ if line.startswith("!"):
+ self._exception = True
+ domain = line[1:]
+ elif line.startswith("*."):
+ self._wild = True
+ domain = line[2:]
+ else:
+ domain = line
+ self._domain = _normalizeHostname(domain)
+
+ def domain(self):
+ "The domain this represents."
+ return self._domain
+
+ def exception(self):
+ "True if this entry's domain denotes does not denote an effective TLD."
+ return self._exception
+
+ def wild(self):
+ "True if this entry represents a class of effective TLDs."
+ return self._wild
+
+
+#################
+# DO EVERYTHING #
+#################
+
+def main(output, effective_tld_filename):
+ """
+ effective_tld_filename is the effective TLD file to parse.
+ A C++ array of { domain, exception, wild } entries representing the
+ eTLD file is then printed to output.
+ """
+
+ def boolStr(b):
+ if b:
+ return "true"
+ return "false"
+
+ for etld in getEffectiveTLDs(effective_tld_filename):
+ exception = boolStr(etld.exception())
+ wild = boolStr(etld.wild())
+ output.write('ETLD_ENTRY("%s", %s, %s)\n' % (etld.domain(), exception, wild))
+
+if __name__ == '__main__':
+ main(sys.stdout, sys.argv[1])
diff --git a/netwerk/dns/punycode.c b/netwerk/dns/punycode.c
new file mode 100644
index 000000000..f905e5272
--- /dev/null
+++ b/netwerk/dns/punycode.c
@@ -0,0 +1,289 @@
+/*
+punycode.c from RFC 3492
+http://www.nicemice.net/idn/
+Adam M. Costello
+http://www.nicemice.net/amc/
+
+This is ANSI C code (C89) implementing Punycode (RFC 3492).
+
+
+C. Disclaimer and license
+
+ Regarding this entire document or any portion of it (including
+ the pseudocode and C code), the author makes no guarantees and
+ is not responsible for any damage resulting from its use. The
+ author grants irrevocable permission to anyone to use, modify,
+ and distribute it in any way that does not diminish the rights
+ of anyone else to use, modify, and distribute it, provided that
+ redistributed derivative works do not contain misleading author or
+ version information. Derivative works need not be licensed under
+ similar terms.
+*/
+
+#include "punycode.h"
+
+/**********************************************************/
+/* Implementation (would normally go in its own .c file): */
+
+#include <string.h>
+
+/*** Bootstring parameters for Punycode ***/
+
+enum { base = 36, tmin = 1, tmax = 26, skew = 38, damp = 700,
+ initial_bias = 72, initial_n = 0x80, delimiter = 0x2D };
+
+/* basic(cp) tests whether cp is a basic code point: */
+#define basic(cp) ((punycode_uint)(cp) < 0x80)
+
+/* delim(cp) tests whether cp is a delimiter: */
+#define delim(cp) ((cp) == delimiter)
+
+/* decode_digit(cp) returns the numeric value of a basic code */
+/* point (for use in representing integers) in the range 0 to */
+/* base-1, or base if cp is does not represent a value. */
+
+static punycode_uint decode_digit(punycode_uint cp)
+{
+ return cp - 48 < 10 ? cp - 22 : cp - 65 < 26 ? cp - 65 :
+ cp - 97 < 26 ? cp - 97 : base;
+}
+
+/* encode_digit(d,flag) returns the basic code point whose value */
+/* (when used for representing integers) is d, which needs to be in */
+/* the range 0 to base-1. The lowercase form is used unless flag is */
+/* nonzero, in which case the uppercase form is used. The behavior */
+/* is undefined if flag is nonzero and digit d has no uppercase form. */
+
+static char encode_digit(punycode_uint d, int flag)
+{
+ return d + 22 + 75 * (d < 26) - ((flag != 0) << 5);
+ /* 0..25 map to ASCII a..z or A..Z */
+ /* 26..35 map to ASCII 0..9 */
+}
+
+/* flagged(bcp) tests whether a basic code point is flagged */
+/* (uppercase). The behavior is undefined if bcp is not a */
+/* basic code point. */
+
+#define flagged(bcp) ((punycode_uint)(bcp) - 65 < 26)
+
+/* encode_basic(bcp,flag) forces a basic code point to lowercase */
+/* if flag is zero, uppercase if flag is nonzero, and returns */
+/* the resulting code point. The code point is unchanged if it */
+/* is caseless. The behavior is undefined if bcp is not a basic */
+/* code point. */
+
+static char encode_basic(punycode_uint bcp, int flag)
+{
+ bcp -= (bcp - 97 < 26) << 5;
+ return bcp + ((!flag && (bcp - 65 < 26)) << 5);
+}
+
+/*** Platform-specific constants ***/
+
+/* maxint is the maximum value of a punycode_uint variable: */
+static const punycode_uint maxint = (punycode_uint) -1;
+/* Because maxint is unsigned, -1 becomes the maximum value. */
+
+/*** Bias adaptation function ***/
+
+static punycode_uint adapt(
+ punycode_uint delta, punycode_uint numpoints, int firsttime )
+{
+ punycode_uint k;
+
+ delta = firsttime ? delta / damp : delta >> 1;
+ /* delta >> 1 is a faster way of doing delta / 2 */
+ delta += delta / numpoints;
+
+ for (k = 0; delta > ((base - tmin) * tmax) / 2; k += base) {
+ delta /= base - tmin;
+ }
+
+ return k + (base - tmin + 1) * delta / (delta + skew);
+}
+
+/*** Main encode function ***/
+
+enum punycode_status punycode_encode(
+ punycode_uint input_length,
+ const punycode_uint input[],
+ const unsigned char case_flags[],
+ punycode_uint *output_length,
+ char output[] )
+{
+ punycode_uint n, delta, h, b, out, max_out, bias, j, m, q, k, t;
+
+ /* Initialize the state: */
+
+ n = initial_n;
+ delta = out = 0;
+ max_out = *output_length;
+ bias = initial_bias;
+
+ /* Handle the basic code points: */
+
+ for (j = 0; j < input_length; ++j) {
+ if (basic(input[j])) {
+ if (max_out - out < 2) return punycode_big_output;
+ output[out++] =
+ case_flags ? encode_basic(input[j], case_flags[j]) : (char)input[j];
+ }
+ /* else if (input[j] < n) return punycode_bad_input; */
+ /* (not needed for Punycode with unsigned code points) */
+ }
+
+ h = b = out;
+
+ /* h is the number of code points that have been handled, b is the */
+ /* number of basic code points, and out is the number of characters */
+ /* that have been output. */
+
+ if (b > 0) output[out++] = delimiter;
+
+ /* Main encoding loop: */
+
+ while (h < input_length) {
+ /* All non-basic code points < n have been */
+ /* handled already. Find the next larger one: */
+
+ for (m = maxint, j = 0; j < input_length; ++j) {
+ /* if (basic(input[j])) continue; */
+ /* (not needed for Punycode) */
+ if (input[j] >= n && input[j] < m) m = input[j];
+ }
+
+ /* Increase delta enough to advance the decoder's */
+ /* <n,i> state to <m,0>, but guard against overflow: */
+
+ if (m - n > (maxint - delta) / (h + 1)) return punycode_overflow;
+ delta += (m - n) * (h + 1);
+ n = m;
+
+ for (j = 0; j < input_length; ++j) {
+ /* Punycode does not need to check whether input[j] is basic: */
+ if (input[j] < n /* || basic(input[j]) */ ) {
+ if (++delta == 0) return punycode_overflow;
+ }
+
+ if (input[j] == n) {
+ /* Represent delta as a generalized variable-length integer: */
+
+ for (q = delta, k = base; ; k += base) {
+ if (out >= max_out) return punycode_big_output;
+ t = k <= bias /* + tmin */ ? tmin : /* +tmin not needed */
+ k >= bias + tmax ? tmax : k - bias;
+ if (q < t) break;
+ output[out++] = encode_digit(t + (q - t) % (base - t), 0);
+ q = (q - t) / (base - t);
+ }
+
+ output[out++] = encode_digit(q, case_flags && case_flags[j]);
+ bias = adapt(delta, h + 1, h == b);
+ delta = 0;
+ ++h;
+ }
+ }
+
+ ++delta, ++n;
+ }
+
+ *output_length = out;
+ return punycode_success;
+}
+
+/*** Main decode function ***/
+
+enum punycode_status punycode_decode(
+ punycode_uint input_length,
+ const char input[],
+ punycode_uint *output_length,
+ punycode_uint output[],
+ unsigned char case_flags[] )
+{
+ punycode_uint n, out, i, max_out, bias,
+ b, j, in, oldi, w, k, digit, t;
+
+ if (!input_length) {
+ return punycode_bad_input;
+ }
+
+ /* Initialize the state: */
+
+ n = initial_n;
+ out = i = 0;
+ max_out = *output_length;
+ bias = initial_bias;
+
+ /* Handle the basic code points: Let b be the number of input code */
+ /* points before the last delimiter, or 0 if there is none, then */
+ /* copy the first b code points to the output. */
+
+ for (b = 0, j = input_length - 1 ; j > 0; --j) {
+ if (delim(input[j])) {
+ b = j;
+ break;
+ }
+ }
+ if (b > max_out) return punycode_big_output;
+
+ for (j = 0; j < b; ++j) {
+ if (case_flags) case_flags[out] = flagged(input[j]);
+ if (!basic(input[j])) return punycode_bad_input;
+ output[out++] = input[j];
+ }
+
+ /* Main decoding loop: Start just after the last delimiter if any */
+ /* basic code points were copied; start at the beginning otherwise. */
+
+ for (in = b > 0 ? b + 1 : 0; in < input_length; ++out) {
+
+ /* in is the index of the next character to be consumed, and */
+ /* out is the number of code points in the output array. */
+
+ /* Decode a generalized variable-length integer into delta, */
+ /* which gets added to i. The overflow checking is easier */
+ /* if we increase i as we go, then subtract off its starting */
+ /* value at the end to obtain delta. */
+
+ for (oldi = i, w = 1, k = base; ; k += base) {
+ if (in >= input_length) return punycode_bad_input;
+ digit = decode_digit(input[in++]);
+ if (digit >= base) return punycode_bad_input;
+ if (digit > (maxint - i) / w) return punycode_overflow;
+ i += digit * w;
+ t = k <= bias /* + tmin */ ? tmin : /* +tmin not needed */
+ k >= bias + tmax ? tmax : k - bias;
+ if (digit < t) break;
+ if (w > maxint / (base - t)) return punycode_overflow;
+ w *= (base - t);
+ }
+
+ bias = adapt(i - oldi, out + 1, oldi == 0);
+
+ /* i was supposed to wrap around from out+1 to 0, */
+ /* incrementing n each time, so we'll fix that now: */
+
+ if (i / (out + 1) > maxint - n) return punycode_overflow;
+ n += i / (out + 1);
+ i %= (out + 1);
+
+ /* Insert n at position i of the output: */
+
+ /* not needed for Punycode: */
+ /* if (decode_digit(n) <= base) return punycode_invalid_input; */
+ if (out >= max_out) return punycode_big_output;
+
+ if (case_flags) {
+ memmove(case_flags + i + 1, case_flags + i, out - i);
+ /* Case of last character determines uppercase flag: */
+ case_flags[i] = flagged(input[in - 1]);
+ }
+
+ memmove(output + i + 1, output + i, (out - i) * sizeof *output);
+ output[i++] = n;
+ }
+
+ *output_length = out;
+ return punycode_success;
+}
diff --git a/netwerk/dns/punycode.h b/netwerk/dns/punycode.h
new file mode 100644
index 000000000..459c6fd75
--- /dev/null
+++ b/netwerk/dns/punycode.h
@@ -0,0 +1,108 @@
+/*
+punycode.c from RFC 3492
+http://www.nicemice.net/idn/
+Adam M. Costello
+http://www.nicemice.net/amc/
+
+This is ANSI C code (C89) implementing Punycode (RFC 3492).
+
+
+
+C. Disclaimer and license
+
+ Regarding this entire document or any portion of it (including
+ the pseudocode and C code), the author makes no guarantees and
+ is not responsible for any damage resulting from its use. The
+ author grants irrevocable permission to anyone to use, modify,
+ and distribute it in any way that does not diminish the rights
+ of anyone else to use, modify, and distribute it, provided that
+ redistributed derivative works do not contain misleading author or
+ version information. Derivative works need not be licensed under
+ similar terms.
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/************************************************************/
+/* Public interface (would normally go in its own .h file): */
+
+#include <limits.h>
+
+enum punycode_status {
+ punycode_success,
+ punycode_bad_input, /* Input is invalid. */
+ punycode_big_output, /* Output would exceed the space provided. */
+ punycode_overflow /* Input needs wider integers to process. */
+};
+
+#if UINT_MAX >= (1 << 26) - 1
+typedef unsigned int punycode_uint;
+#else
+typedef unsigned long punycode_uint;
+#endif
+
+enum punycode_status punycode_encode(
+ punycode_uint input_length,
+ const punycode_uint input[],
+ const unsigned char case_flags[],
+ punycode_uint *output_length,
+ char output[] );
+
+ /* punycode_encode() converts Unicode to Punycode. The input */
+ /* is represented as an array of Unicode code points (not code */
+ /* units; surrogate pairs are not allowed), and the output */
+ /* will be represented as an array of ASCII code points. The */
+ /* output string is *not* null-terminated; it will contain */
+ /* zeros if and only if the input contains zeros. (Of course */
+ /* the caller can leave room for a terminator and add one if */
+ /* needed.) The input_length is the number of code points in */
+ /* the input. The output_length is an in/out argument: the */
+ /* caller passes in the maximum number of code points that it */
+ /* can receive, and on successful return it will contain the */
+ /* number of code points actually output. The case_flags array */
+ /* holds input_length boolean values, where nonzero suggests that */
+ /* the corresponding Unicode character be forced to uppercase */
+ /* after being decoded (if possible), and zero suggests that */
+ /* it be forced to lowercase (if possible). ASCII code points */
+ /* are encoded literally, except that ASCII letters are forced */
+ /* to uppercase or lowercase according to the corresponding */
+ /* uppercase flags. If case_flags is a null pointer then ASCII */
+ /* letters are left as they are, and other code points are */
+ /* treated as if their uppercase flags were zero. The return */
+ /* value can be any of the punycode_status values defined above */
+ /* except punycode_bad_input; if not punycode_success, then */
+ /* output_size and output might contain garbage. */
+
+enum punycode_status punycode_decode(
+ punycode_uint input_length,
+ const char input[],
+ punycode_uint *output_length,
+ punycode_uint output[],
+ unsigned char case_flags[] );
+
+ /* punycode_decode() converts Punycode to Unicode. The input is */
+ /* represented as an array of ASCII code points, and the output */
+ /* will be represented as an array of Unicode code points. The */
+ /* input_length is the number of code points in the input. The */
+ /* output_length is an in/out argument: the caller passes in */
+ /* the maximum number of code points that it can receive, and */
+ /* on successful return it will contain the actual number of */
+ /* code points output. The case_flags array needs room for at */
+ /* least output_length values, or it can be a null pointer if the */
+ /* case information is not needed. A nonzero flag suggests that */
+ /* the corresponding Unicode character be forced to uppercase */
+ /* by the caller (if possible), while zero suggests that it be */
+ /* forced to lowercase (if possible). ASCII code points are */
+ /* output already in the proper case, but their flags will be set */
+ /* appropriately so that applying the flags would be harmless. */
+ /* The return value can be any of the punycode_status values */
+ /* defined above; if not punycode_success, then output_length, */
+ /* output, and case_flags might contain garbage. On success, the */
+ /* decoder will never need to write an output_length greater than */
+ /* input_length, because of how the encoding is defined. */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */