Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
251if ((msg_pos + sizeof(rt_msghdr)) > buf.size()) return std::nullopt;252const struct rt_msghdr* rt = (const struct rt_msghdr*)(buf.data() + msg_pos);253const size_t next_msg_pos = msg_pos + rt->rtm_msglen;254if (rt->rtm_msglen < sizeof(rt_msghdr) || next_msg_pos > buf.size()) return std::nullopt;255// Iterate over addresses within message, get destination and gateway (if present).256// Address data starts after header.257size_t sa_pos = msg_pos + sizeof(struct rt_msghdr);258std::optional<CNetAddr> dst, gateway;259for (int i = 0; i < RTAX_MAX; i++) {260if (rt->rtm_addrs & (1 << i)) {261// 2 is just sa_len + sa_family, the theoretical minimum size of a socket address.262if ((sa_pos + 2) > next_msg_pos) return std::nullopt;263const struct sockaddr* sa = (const struct sockaddr*)(buf.data() + sa_pos);264if ((sa_pos + sa->sa_len) > next_msg_pos) return std::nullopt;265if (i == RTAX_DST) {266dst = FromSockAddr(sa, sa->sa_len);267} else if (i == RTAX_GATEWAY) {268gateway = FromSockAddr(sa, sa->sa_len);269}270// Skip sockaddr entries for bit flags we're not interested in,271// move cursor.272sa_pos += ROUNDUP32(sa->sa_len);273}274}275// Found default gateway?276if (dst && gateway && dst->IsBindAny()) { // Route to 0.0.0.0 or :: ?277return *gateway;278}279// Skip to next message.280msg_pos = next_msg_pos;281}282return std::nullopt;283}285#else287// Dummy implementation.288std::optional<CNetAddr> QueryDefaultGatewayImpl(sa_family_t)289{290return std::nullopt;291}293#endif295}297std::optional<CNetAddr> QueryDefaultGateway(Network network)298{299Assume(network == NET_IPV4 || network == NET_IPV6);301sa_family_t family;302if (network == NET_IPV4) {303family = AF_INET;304} else if(network == NET_IPV6) {305family = AF_INET6;306} else {307return std::nullopt;308}310std::optional<CNetAddr> ret = QueryDefaultGatewayImpl(family);312// It's possible for the default gateway to be 0.0.0.0 or ::0 on at least Windows313// for some routing strategies. If so, return as if no default gateway was found.314if (ret && !ret->IsBindAny()) {315return ret;316} else {317return std::nullopt;318}319}321std::vector<CNetAddr> GetLocalAddresses()322{323std::vector<CNetAddr> addresses;324#ifdef WIN32325DWORD status = 0;326constexpr size_t MAX_ADAPTER_ADDR_SIZE = 4 * 1000 * 1000; // Absolute maximum size of adapter addresses structure we're willing to handle, as a precaution.327std::vector<std::byte> out_buf(15000, {}); // Start with 15KB allocation as recommended in GetAdaptersAddresses documentation.328while (true) {329ULONG out_buf_len = out_buf.size();330status = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME,331nullptr, reinterpret_cast<PIP_ADAPTER_ADDRESSES>(out_buf.data()), &out_buf_len);332if (status == ERROR_BUFFER_OVERFLOW && out_buf.size() < MAX_ADAPTER_ADDR_SIZE) {333// If status == ERROR_BUFFER_OVERFLOW, out_buf_len will contain the needed size.334// Unfortunately, this cannot be fully relied on, because another process may have added interfaces.335// So to avoid getting stuck due to a race condition, double the buffer size at least336// once before retrying (but only up to the maximum allowed size).337out_buf.resize(std::min(std::max<size_t>(out_buf_len, out_buf.size()) * 2, MAX_ADAPTER_ADDR_SIZE));338} else {339break;340}341}343if (status != NO_ERROR) {344// This includes ERROR_NO_DATA if there are no addresses and thus there's not even one PIP_ADAPTER_ADDRESSES345// record in the returned structure.346LogError("Could not get local adapter addresses: %s\n", NetworkErrorString(status));347return addresses;348}350// Iterate over network adapters.351for (PIP_ADAPTER_ADDRESSES cur_adapter = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(out_buf.data());352cur_adapter != nullptr; cur_adapter = cur_adapter->Next) {353if (cur_adapter->OperStatus != IfOperStatusUp) continue;354if (cur_adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK) continue;356// Iterate over unicast addresses for adapter, the only address type we're interested in.357for (PIP_ADAPTER_UNICAST_ADDRESS cur_address = cur_adapter->FirstUnicastAddress;358cur_address != nullptr; cur_address = cur_address->Next) {359// "The IP address is a cluster address and should not be used by most applications."360if ((cur_address->Flags & IP_ADAPTER_ADDRESS_TRANSIENT) != 0) continue;362if (std::optional<CNetAddr> addr = FromSockAddr(cur_address->Address.lpSockaddr, static_cast<socklen_t>(cur_address->Address.iSockaddrLength))) {363addresses.push_back(*addr);364}365}366}367#elif defined(HAVE_IFADDRS)368struct ifaddrs* myaddrs;369if (getifaddrs(&myaddrs) == 0) {370for (struct ifaddrs* ifa = myaddrs; ifa != nullptr; ifa = ifa->ifa_next)371{372if (ifa->ifa_addr == nullptr) continue;373if ((ifa->ifa_flags & IFF_UP) == 0) continue;374if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) continue;376if (std::optional<CNetAddr> addr = FromSockAddr(ifa->ifa_addr, std::nullopt)) {377addresses.push_back(*addr);378}379}380freeifaddrs(myaddrs);381}382#endif383return addresses;384}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.