@@ -0,0 +1,180 @@
+From: Robert O'Callahan <rocallahan@novell.com>
+Subject: proxy.pac: host resolution error
+References:
+https://bugzilla.novell.com/show_bug.cgi?id=196506
+https://bugzilla.mozilla.org/show_bug.cgi?id=347307
+
+diff --git a/netwerk/base/src/nsProxyAutoConfig.js b/netwerk/base/src/nsProxyAutoConfig.js
+index 6a34044..2186502 100644
+--- a/netwerk/base/src/nsProxyAutoConfig.js
++++ b/netwerk/base/src/nsProxyAutoConfig.js
+@@ -50,7 +50,7 @@ const kPAC_CID = Components.ID("{63ac8c66-1dd2-11b2-b070-84d00d3eaece}");
+
+ const nsISupports = Components.interfaces.nsISupports;
+ const nsIProxyAutoConfig = Components.interfaces.nsIProxyAutoConfig;
+-const nsIDNSService = Components.interfaces.nsIDNSService;
++const nsPIDNSService = Components.interfaces.nsPIDNSService;
+
+ // implementor of nsIProxyAutoConfig
+ function nsProxyAutoConfig() {};
+@@ -114,7 +114,7 @@ function proxyAlert(msg) {
+ // wrapper for getting local IP address called by PAC file
+ function myIpAddress() {
+ try {
+- return dns.resolve(dns.myHostName, 0).getNextAddrAsString();
++ return dns.getNetworkAddrAsString();
+ } catch (e) {
+ return '127.0.0.1';
+ }
+@@ -176,7 +176,7 @@ function NSGetModule(compMgr, fileSpec) {
+ }
+
+ var pac = new nsProxyAutoConfig() ;
+-var dns = Components.classes[kDNS_CONTRACTID].getService(nsIDNSService);
++var dns = Components.classes[kDNS_CONTRACTID].getService(nsPIDNSService);
+
+ var pacUtils =
+ "function dnsDomainIs(host, domain) {\n" +
+diff --git a/netwerk/dns/public/nsPIDNSService.idl b/netwerk/dns/public/nsPIDNSService.idl
+index e0eea6d..1abb223 100644
+--- a/netwerk/dns/public/nsPIDNSService.idl
++++ b/netwerk/dns/public/nsPIDNSService.idl
+@@ -58,4 +58,11 @@ interface nsPIDNSService : nsIDNSService
+ * this method.
+ */
+ void shutdown();
++
++ /**
++ * Returns the IP address of the machine that is most suitable for
++ * identifying the machine's network. Favour VPN addresses above
++ * wired/wireless addresses above 127.x.x.x addresses.
++ */
++ ACString getNetworkAddrAsString();
+ };
+diff --git a/netwerk/dns/src/nsDNSService2.cpp b/netwerk/dns/src/nsDNSService2.cpp
+index f38e0c1..e928a76 100644
+--- a/netwerk/dns/src/nsDNSService2.cpp
++++ b/netwerk/dns/src/nsDNSService2.cpp
+@@ -56,6 +56,11 @@
+ #include "prio.h"
+ #include "plstr.h"
+
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <ifaddrs.h>
++#include <net/if.h>
++
+ static const char kPrefDnsCacheEntries[] = "network.dnsCacheEntries";
+ static const char kPrefDnsCacheExpiration[] = "network.dnsCacheExpiration";
+ static const char kPrefEnableIDN[] = "network.enableIDN";
+@@ -135,6 +140,18 @@ nsDNSRecord::GetNextAddr(PRUint16 port, PRNetAddr *addr)
+ return NS_OK;
+ }
+
++static nsresult
++AddrToString(PRNetAddr* aAddr, nsACString& aResult)
++{
++ char buf[64];
++ if (PR_NetAddrToString(aAddr, buf, sizeof(buf)) == PR_SUCCESS) {
++ aResult.Assign(buf);
++ return NS_OK;
++ }
++ NS_ERROR("PR_NetAddrToString failed unexpectedly");
++ return NS_ERROR_FAILURE; // conversion failed for some reason
++}
++
+ NS_IMETHODIMP
+ nsDNSRecord::GetNextAddrAsString(nsACString &result)
+ {
+@@ -142,13 +159,7 @@ nsDNSRecord::GetNextAddrAsString(nsACString &result)
+ nsresult rv = GetNextAddr(0, &addr);
+ if (NS_FAILED(rv)) return rv;
+
+- char buf[64];
+- if (PR_NetAddrToString(&addr, buf, sizeof(buf)) == PR_SUCCESS) {
+- result.Assign(buf);
+- return NS_OK;
+- }
+- NS_ERROR("PR_NetAddrToString failed unexpectedly");
+- return NS_ERROR_FAILURE; // conversion failed for some reason
++ return AddrToString(&addr, result);
+ }
+
+ NS_IMETHODIMP
+@@ -580,3 +591,76 @@ nsDNSService::GetAFForLookup(const nsACString &host)
+
+ return af;
+ }
++
++static PRInt32
++GetScoreForInterface(struct ifaddrs* aInterface)
++{
++ // Interface must be up
++ if (!(aInterface->ifa_flags & IFF_UP))
++ return 0;
++ // Interface must be configured
++ if (!(aInterface->ifa_flags & IFF_RUNNING))
++ return 0;
++
++ // Interface must have an address
++ if (aInterface->ifa_addr == NULL)
++ return 0;
++
++ // Interface must have an address
++ if (aInterface->ifa_addr == NULL)
++ return 0;
++
++ // Only look at IP interfaces
++ sa_family_t type = aInterface->ifa_addr->sa_family;
++ if (type != AF_INET && type != AF_INET6)
++ return 0;
++
++ // Loopback interfaces get the lowest score
++ if (aInterface->ifa_flags & IFF_LOOPBACK)
++ return 1;
++
++ if (strchr(aInterface->ifa_name, ':')) {
++ // guess that it's probably a VPN address
++ return 3;
++ }
++
++ // Regular interface
++ return 2;
++}
++
++nsresult
++SockaddrToString(struct sockaddr* aAddr, nsACString& aResult)
++{
++ PRNetAddr* addr = NS_REINTERPRET_CAST(PRNetAddr*, aAddr);
++ return AddrToString(addr, aResult);
++}
++
++NS_IMETHODIMP
++nsDNSService::GetNetworkAddrAsString(nsACString& aResult)
++{
++ aResult.AssignLiteral("127.0.0.1");
++
++ struct ifaddrs* addrs;
++ if (getifaddrs(&addrs) < 0)
++ return NS_OK;
++
++ struct ifaddrs* bestAddr = nsnull;
++ PRInt32 bestScore = 0;
++ struct ifaddrs* addr;
++ for (addr = addrs; addr; addr = addr->ifa_next) {
++ PRInt32 score = GetScoreForInterface(addr);
++ if (score > 0 && (!bestAddr || score > bestScore)) {
++ bestAddr = addr;
++ bestScore = score;
++ }
++ }
++
++ if (!bestAddr) {
++ freeifaddrs(addrs);
++ return NS_OK;
++ }
++
++ nsresult rv = SockaddrToString(bestAddr->ifa_addr, aResult);
++ freeifaddrs(addrs);
++ return rv;
++}
|