Bug 1326483 - Part 1, not allow non-loopback UDP socket be created in offline mode. r=drno
MozReview-Commit-ID: IpnHjmW3RYr
--- a/netwerk/base/nsUDPSocket.cpp
+++ b/netwerk/base/nsUDPSocket.cpp
@@ -66,16 +66,32 @@ ResolveHost(const nsACString &host, nsID
}
nsCOMPtr<nsICancelable> tmpOutstanding;
return dns->AsyncResolve(host, 0, listener, nullptr,
getter_AddRefs(tmpOutstanding));
}
+static nsresult
+CheckIOStatus(const NetAddr *aAddr)
+{
+ MOZ_ASSERT(gIOService);
+
+ if (gIOService->IsNetTearingDown()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ if (gIOService->IsOffline() && !IsLoopBackAddress(aAddr)) {
+ return NS_ERROR_OFFLINE;
+ }
+
+ return NS_OK;
+}
+
//-----------------------------------------------------------------------------
class SetSocketOptionRunnable : public Runnable
{
public:
SetSocketOptionRunnable(nsUDPSocket* aSocket, const PRSocketOptionData& aOpt)
: mSocket(aSocket)
, mOpt(aOpt)
@@ -315,18 +331,19 @@ nsUDPSocket::OnMsgAttach()
nsresult
nsUDPSocket::TryAttach()
{
nsresult rv;
if (!gSocketTransportService)
return NS_ERROR_FAILURE;
- if (gIOService->IsNetTearingDown()) {
- return NS_ERROR_FAILURE;
+ rv = CheckIOStatus(&mAddr);
+ if (NS_FAILED(rv)) {
+ return rv;
}
//
// 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
@@ -525,17 +542,17 @@ nsUDPSocket::OnSocketDetached(PRFileDesc
}
}
}
void
nsUDPSocket::IsLocal(bool *aIsLocal)
{
// If bound to loopback, this UDP socket only accepts local connections.
- *aIsLocal = mAddr.raw.family == nsINetAddr::FAMILY_LOCAL;
+ *aIsLocal = IsLoopBackAddress(&mAddr);
}
//-----------------------------------------------------------------------------
// nsSocket::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS(nsUDPSocket, nsIUDPSocket)
@@ -568,40 +585,54 @@ NS_IMETHODIMP
nsUDPSocket::Init2(const nsACString& aAddr, int32_t aPort, nsIPrincipal *aPrincipal,
bool aAddressReuse, uint8_t aOptionalArgc)
{
if (NS_WARN_IF(aAddr.IsEmpty())) {
return NS_ERROR_INVALID_ARG;
}
PRNetAddr prAddr;
+ memset(&prAddr, 0, sizeof(prAddr));
if (PR_StringToNetAddr(aAddr.BeginReading(), &prAddr) != PR_SUCCESS) {
return NS_ERROR_FAILURE;
}
- NetAddr addr;
-
- if (aPort < 0)
+ if (aPort < 0) {
aPort = 0;
+ }
- addr.raw.family = AF_INET;
- addr.inet.port = htons(aPort);
- addr.inet.ip = prAddr.inet.ip;
+ switch (prAddr.raw.family) {
+ case PR_AF_INET:
+ prAddr.inet.port = PR_htons(aPort);
+ break;
+ case PR_AF_INET6:
+ prAddr.ipv6.port = PR_htons(aPort);
+ break;
+ default:
+ MOZ_ASSERT_UNREACHABLE("Dont accept address other than IPv4 and IPv6");
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+
+ NetAddr addr;
+ PRNetAddrToNetAddr(&prAddr, &addr);
return InitWithAddress(&addr, aPrincipal, aAddressReuse, aOptionalArgc);
}
NS_IMETHODIMP
nsUDPSocket::InitWithAddress(const NetAddr *aAddr, nsIPrincipal *aPrincipal,
bool aAddressReuse, uint8_t aOptionalArgc)
{
NS_ENSURE_TRUE(mFD == nullptr, NS_ERROR_ALREADY_INITIALIZED);
- if (gIOService->IsNetTearingDown()) {
- return NS_ERROR_FAILURE;
+ nsresult rv;
+
+ rv = CheckIOStatus(aAddr);
+ if (NS_FAILED(rv)) {
+ return rv;
}
bool addressReuse = (aOptionalArgc == 1) ? aAddressReuse : true;
//
// configure listening socket...
//
@@ -670,16 +701,23 @@ nsUDPSocket::Connect(const NetAddr *aAdd
UDPSOCKET_LOG(("nsUDPSocket::Connect [this=%p]\n", this));
NS_ENSURE_ARG(aAddr);
if (NS_WARN_IF(!mFD)) {
return NS_ERROR_NOT_INITIALIZED;
}
+ nsresult rv;
+
+ rv = CheckIOStatus(aAddr);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
bool onSTSThread = false;
mSts->IsOnCurrentThread(&onSTSThread);
NS_ASSERTION(onSTSThread, "NOT ON STS THREAD");
if (!onSTSThread) {
return NS_ERROR_FAILURE;
}
PRNetAddr prAddr;