mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-01 09:35:52 -05:00
net: Add optional length checking to CService::SetSockAddr
In almost all cases (the only exception is `getifaddrs`), we know the size of the data passed into SetSockAddr, so we can check this to be what is expected.
This commit is contained in:
parent
35bf426e02
commit
23231c1e64
5 changed files with 15 additions and 13 deletions
|
@ -169,16 +169,9 @@ std::optional<CNetAddr> QueryDefaultGatewayImpl(sa_family_t family)
|
||||||
|
|
||||||
std::optional<CNetAddr> FromSockAddr(const struct sockaddr* addr)
|
std::optional<CNetAddr> FromSockAddr(const struct sockaddr* addr)
|
||||||
{
|
{
|
||||||
// Check valid length. Note that sa_len is not part of POSIX, and exists on MacOS and some BSDs only, so we can't
|
|
||||||
// do this check in SetSockAddr.
|
|
||||||
if (!(addr->sa_family == AF_INET && addr->sa_len == sizeof(struct sockaddr_in)) &&
|
|
||||||
!(addr->sa_family == AF_INET6 && addr->sa_len == sizeof(struct sockaddr_in6))) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill in a CService from the sockaddr, then drop the port part.
|
// Fill in a CService from the sockaddr, then drop the port part.
|
||||||
CService service;
|
CService service;
|
||||||
if (service.SetSockAddr(addr)) {
|
if (service.SetSockAddr(addr, addr->sa_len)) {
|
||||||
return (CNetAddr)service;
|
return (CNetAddr)service;
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
|
@ -426,7 +426,7 @@ std::variant<MappingResult, MappingError> PCPRequestPortMap(const PCPMappingNonc
|
||||||
return MappingError::NETWORK_ERROR;
|
return MappingError::NETWORK_ERROR;
|
||||||
}
|
}
|
||||||
CService internal;
|
CService internal;
|
||||||
if (!internal.SetSockAddr((struct sockaddr*)&internal_addr)) return MappingError::NETWORK_ERROR;
|
if (!internal.SetSockAddr((struct sockaddr*)&internal_addr, internal_addrlen)) return MappingError::NETWORK_ERROR;
|
||||||
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "pcp: Internal address after connect: %s\n", internal.ToStringAddr());
|
LogPrintLevel(BCLog::NET, BCLog::Level::Debug, "pcp: Internal address after connect: %s\n", internal.ToStringAddr());
|
||||||
|
|
||||||
// Build request packet. Make sure the packet is zeroed so that reserved fields are zero
|
// Build request packet. Make sure the packet is zeroed so that reserved fields are zero
|
||||||
|
|
|
@ -383,7 +383,7 @@ static CAddress GetBindAddress(const Sock& sock)
|
||||||
struct sockaddr_storage sockaddr_bind;
|
struct sockaddr_storage sockaddr_bind;
|
||||||
socklen_t sockaddr_bind_len = sizeof(sockaddr_bind);
|
socklen_t sockaddr_bind_len = sizeof(sockaddr_bind);
|
||||||
if (!sock.GetSockName((struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) {
|
if (!sock.GetSockName((struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) {
|
||||||
addr_bind.SetSockAddr((const struct sockaddr*)&sockaddr_bind);
|
addr_bind.SetSockAddr((const struct sockaddr*)&sockaddr_bind, sockaddr_bind_len);
|
||||||
} else {
|
} else {
|
||||||
LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "getsockname failed\n");
|
LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "getsockname failed\n");
|
||||||
}
|
}
|
||||||
|
@ -1728,7 +1728,7 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) {
|
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr, len)) {
|
||||||
LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "Unknown socket family\n");
|
LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "Unknown socket family\n");
|
||||||
} else {
|
} else {
|
||||||
addr = CAddress{MaybeFlipIPv6toCJDNS(addr), NODE_NONE};
|
addr = CAddress{MaybeFlipIPv6toCJDNS(addr), NODE_NONE};
|
||||||
|
|
|
@ -807,13 +807,15 @@ CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr, a
|
||||||
assert(addr.sin6_family == AF_INET6);
|
assert(addr.sin6_family == AF_INET6);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CService::SetSockAddr(const struct sockaddr *paddr)
|
bool CService::SetSockAddr(const struct sockaddr *paddr, socklen_t addrlen)
|
||||||
{
|
{
|
||||||
switch (paddr->sa_family) {
|
switch (paddr->sa_family) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
|
if (addrlen != sizeof(struct sockaddr_in)) return false;
|
||||||
*this = CService(*(const struct sockaddr_in*)paddr);
|
*this = CService(*(const struct sockaddr_in*)paddr);
|
||||||
return true;
|
return true;
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
|
if (addrlen != sizeof(struct sockaddr_in6)) return false;
|
||||||
*this = CService(*(const struct sockaddr_in6*)paddr);
|
*this = CService(*(const struct sockaddr_in6*)paddr);
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -539,7 +539,14 @@ public:
|
||||||
explicit CService(const struct sockaddr_in& addr);
|
explicit CService(const struct sockaddr_in& addr);
|
||||||
uint16_t GetPort() const;
|
uint16_t GetPort() const;
|
||||||
bool GetSockAddr(struct sockaddr* paddr, socklen_t* addrlen) const;
|
bool GetSockAddr(struct sockaddr* paddr, socklen_t* addrlen) const;
|
||||||
bool SetSockAddr(const struct sockaddr* paddr);
|
/**
|
||||||
|
* Set CService from a network sockaddr.
|
||||||
|
* @param[in] paddr Pointer to sockaddr structure
|
||||||
|
* @param[in] addrlen Length of sockaddr structure in bytes. This will be checked to exactly match the length of
|
||||||
|
* a socket address of the provided family, unless std::nullopt is passed
|
||||||
|
* @returns true on success
|
||||||
|
*/
|
||||||
|
bool SetSockAddr(const struct sockaddr* paddr, socklen_t addrlen);
|
||||||
/**
|
/**
|
||||||
* Get the address family
|
* Get the address family
|
||||||
* @returns AF_UNSPEC if unspecified
|
* @returns AF_UNSPEC if unspecified
|
||||||
|
|
Loading…
Add table
Reference in a new issue