MCPcopy Create free account
hub / github.com/bitcoin/bitcoin / QueryDefaultGatewayImpl

Function QueryDefaultGatewayImpl

src/common/netif.cpp:71–188  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

69static constexpr ssize_t NETLINK_MAX_RESPONSE_SIZE{1'048'576};
70
71std::optional<CNetAddr> QueryDefaultGatewayImpl(sa_family_t family)
72{
73 // Create a netlink socket.
74 auto sock{CreateSock(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)};
75 if (!sock) {
76 LogError("socket(AF_NETLINK): %s\n", NetworkErrorString(errno));
77 return std::nullopt;
78 }
79
80 // Send request.
81 struct {
82 nlmsghdr hdr; ///< Request header.
83 rtmsg data; ///< Request data, a "route message".
84 nlattr dst_hdr; ///< One attribute, conveying the route destination address.
85 char dst_data[16]; ///< Route destination address. To query the default route we use 0.0.0.0/0 or [::]/0. For IPv4 the first 4 bytes are used.
86 } request{};
87
88 // Whether to use the first 4 or 16 bytes from request.dst_data.
89 const size_t dst_data_len = family == AF_INET ? 4 : 16;
90
91 request.hdr.nlmsg_type = RTM_GETROUTE;
92 request.hdr.nlmsg_flags = NLM_F_REQUEST;
93#ifdef __linux__
94 // Linux IPv4 / IPv6 - this must be present, otherwise no gateway is found
95 // FreeBSD IPv4 - does not matter, the gateway is found with or without this
96 // FreeBSD IPv6 - this must be absent, otherwise no gateway is found
97 request.hdr.nlmsg_flags |= NLM_F_DUMP;
98#endif
99 request.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(rtmsg) + sizeof(nlattr) + dst_data_len);
100 request.hdr.nlmsg_seq = 0; // Sequence number, used to match which reply is to which request. Irrelevant for us because we send just one request.
101 request.data.rtm_family = family;
102 request.data.rtm_dst_len = 0; // Prefix length.
103#ifdef __FreeBSD__
104 // Linux IPv4 / IPv6 this must be absent, otherwise no gateway is found
105 // FreeBSD IPv4 - does not matter, the gateway is found with or without this
106 // FreeBSD IPv6 - this must be present, otherwise no gateway is found
107 request.data.rtm_flags = RTM_F_PREFIX;
108#endif
109 request.dst_hdr.nla_type = RTA_DST;
110 request.dst_hdr.nla_len = sizeof(nlattr) + dst_data_len;
111
112 if (sock->Send(&request, request.hdr.nlmsg_len, 0) != static_cast<ssize_t>(request.hdr.nlmsg_len)) {
113 LogError("send() to netlink socket: %s\n", NetworkErrorString(errno));
114 return std::nullopt;
115 }
116
117 // Receive response.
118 char response[4096];
119 ssize_t total_bytes_read{0};
120 bool done{false};
121 while (!done) {
122 int64_t recv_result;
123 do {
124 recv_result = sock->Recv(response, sizeof(response), 0);
125 } while (recv_result < 0 && (errno == EINTR || errno == EAGAIN));
126 if (recv_result < 0) {
127 LogError("recv() from netlink socket: %s\n", NetworkErrorString(errno));
128 return std::nullopt;

Callers 1

QueryDefaultGatewayFunction · 0.85

Calls 8

NetworkErrorStringFunction · 0.85
CNetAddrClass · 0.85
FromSockAddrFunction · 0.85
IsBindAnyMethod · 0.80
SendMethod · 0.45
RecvMethod · 0.45
dataMethod · 0.45
sizeMethod · 0.45

Tested by

no test coverage detected