1
// libTorrent - BitTorrent library
2
// Copyright (C) 2005-2007, Jari Sundell
4
// This program is free software; you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation; either version 2 of the License, or
7
// (at your option) any later version.
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU General Public License for more details.
14
// You should have received a copy of the GNU General Public License
15
// along with this program; if not, write to the Free Software
16
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
// In addition, as a special exception, the copyright holders give
19
// permission to link the code of portions of this program with the
20
// OpenSSL library under certain conditions as described in each
21
// individual source file, and distribute linked combinations
24
// You must obey the GNU General Public License in all respects for
25
// all of the code used other than OpenSSL. If you modify file(s)
26
// with this exception, you may extend this exception to your version
27
// of the file(s), but you are not obligated to do so. If you do not
28
// wish to do so, delete this exception statement from your version.
29
// If you delete this exception statement from all source files in the
30
// program, then also delete it here.
32
// Contact: Jari Sundell <jaris@ifi.uio.no>
35
// 3185 Skoppum, NORWAY
41
#include <rak/socket_address.h>
42
#include <sys/types.h>
46
#include <linux/netlink.h>
47
#include <linux/rtnetlink.h>
50
#include "torrent/exceptions.h"
51
#include "socket_fd.h"
52
#include "local_addr.h"
57
// IPv4 priority, from highest to lowest:
59
// 1. Everything else (global address)
60
// 2. Private address space (10.0.0.0/8, 172.16.0.0/16, 192.168.0.0/24)
61
// 3. Empty/INADDR_ANY (0.0.0.0)
62
// 4. Link-local address (169.254.0.0/16)
63
// 5. Localhost (127.0.0.0/8)
64
int get_priority_ipv4(const in_addr& addr) {
65
if ((addr.s_addr & htonl(0xff000000U)) == htonl(0x7f000000U)) {
68
if (addr.s_addr == htonl(0)) {
71
if ((addr.s_addr & htonl(0xffff0000U)) == htonl(0xa9fe0000U)) {
74
if ((addr.s_addr & htonl(0xff000000U)) == htonl(0x0a000000U) ||
75
(addr.s_addr & htonl(0xffff0000U)) == htonl(0xac100000U) ||
76
(addr.s_addr & htonl(0xffff0000U)) == htonl(0xc0a80000U)) {
83
// IPv6 priority, from highest to lowest:
85
// 1. Global address (2000::/16 not in 6to4 or Teredo)
86
// 2. 6to4 (2002::/16)
87
// 3. Teredo (2001::/32)
88
// 4. Empty/INADDR_ANY (::)
89
// 5. Everything else (link-local, ULA, etc.)
90
int get_priority_ipv6(const in6_addr& addr) {
91
const uint32_t *addr32 = reinterpret_cast<const uint32_t *>(addr.s6_addr);
92
if (addr32[0] == htonl(0) &&
93
addr32[1] == htonl(0) &&
94
addr32[2] == htonl(0) &&
95
addr32[3] == htonl(0)) {
98
if (addr32[0] == htonl(0x20010000)) {
101
if ((addr32[0] & htonl(0xffff0000)) == htonl(0x20020000)) {
104
if ((addr32[0] & htonl(0xe0000000)) == htonl(0x20000000)) {
111
int get_priority(const rak::socket_address& addr) {
112
switch (addr.family()) {
114
return get_priority_ipv4(addr.c_sockaddr_inet()->sin_addr);
117
return get_priority_ipv6(addr.c_sockaddr_inet6()->sin6_addr);
120
throw torrent::internal_error("Unknown address family given to compare");
128
// Linux-specific implementation that understands how to filter away
129
// understands how to filter away secondary addresses.
130
bool get_local_address(sa_family_t family, rak::socket_address *address) {
132
if (getifaddrs(&ifaddrs)) {
136
rak::socket_address best_addr;
139
best_addr.sa_inet()->clear();
143
best_addr.sa_inet6()->clear();
147
throw torrent::internal_error("Unknown address family given to get_local_address");
150
// The bottom bit of the priority is used to hold if the address is
151
// a secondary address (e.g. with IPv6 privacy extensions) or not;
152
// secondary addresses have lower priority (higher number).
153
int best_addr_pri = get_priority(best_addr) * 2;
155
// Get all the addresses via Linux' netlink interface.
156
int fd = ::socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
161
struct sockaddr_nl nladdr;
162
memset(&nladdr, 0, sizeof(nladdr));
163
nladdr.nl_family = AF_NETLINK;
164
if (::bind(fd, (sockaddr *)&nladdr, sizeof(nladdr))) {
169
const int seq_no = 1;
174
memset(&req, 0, sizeof(req));
176
req.nh.nlmsg_len = sizeof(req);
177
req.nh.nlmsg_type = RTM_GETADDR;
178
req.nh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
179
req.nh.nlmsg_pid = getpid();
180
req.nh.nlmsg_seq = seq_no;
181
req.g.rtgen_family = AF_UNSPEC;
185
ret = ::sendto(fd, &req, sizeof(req), 0, (sockaddr *)&nladdr, sizeof(nladdr));
186
} while (ret == -1 && errno == EINTR);
196
socklen_t len = sizeof(nladdr);
198
ret = ::recvfrom(fd, buf, sizeof(buf), 0, (sockaddr *)&nladdr, &len);
199
} while (ret == -1 && errno == EINTR);
206
for (const nlmsghdr *nlmsg = (const nlmsghdr *)buf;
207
NLMSG_OK(nlmsg, ret);
208
nlmsg = NLMSG_NEXT(nlmsg, ret)) {
209
if (nlmsg->nlmsg_seq != seq_no)
211
if (nlmsg->nlmsg_type == NLMSG_DONE) {
215
if (nlmsg->nlmsg_type == NLMSG_ERROR) {
219
if (nlmsg->nlmsg_type != RTM_NEWADDR)
222
const ifaddrmsg *ifa = (const ifaddrmsg *)NLMSG_DATA(nlmsg);
224
if (ifa->ifa_family != family)
227
#ifdef IFA_F_OPTIMISTIC
228
if ((ifa->ifa_flags & IFA_F_OPTIMISTIC) != 0)
231
#ifdef IFA_F_DADFAILED
232
if ((ifa->ifa_flags & IFA_F_DADFAILED) != 0)
235
#ifdef IFA_F_DEPRECATED
236
if ((ifa->ifa_flags & IFA_F_DEPRECATED) != 0)
239
#ifdef IFA_F_TENTATIVE
240
if ((ifa->ifa_flags & IFA_F_TENTATIVE) != 0)
244
// Since there can be point-to-point links on the machine, we need to keep
245
// track of the addresses we've seen for this interface; if we see both
246
// IFA_LOCAL and IFA_ADDRESS for an interface, keep only the IFA_LOCAL.
247
rak::socket_address this_addr;
248
bool seen_addr = false;
249
int plen = IFA_PAYLOAD(nlmsg);
250
for (const rtattr *rta = IFA_RTA(ifa);
252
rta = RTA_NEXT(rta, plen)) {
253
if (rta->rta_type != IFA_LOCAL &&
254
rta->rta_type != IFA_ADDRESS) {
257
if (rta->rta_type == IFA_ADDRESS && seen_addr) {
261
switch (ifa->ifa_family) {
263
this_addr.sa_inet()->clear();
264
this_addr.sa_inet()->set_address(*(const in_addr *)RTA_DATA(rta));
268
this_addr.sa_inet6()->clear();
269
this_addr.sa_inet6()->set_address(*(const in6_addr *)RTA_DATA(rta));
277
int this_addr_pri = get_priority(this_addr) * 2;
278
if ((ifa->ifa_flags & IFA_F_SECONDARY) == IFA_F_SECONDARY) {
282
if (this_addr_pri < best_addr_pri) {
283
best_addr = this_addr;
284
best_addr_pri = this_addr_pri;
290
if (!best_addr.is_address_any()) {
291
*address = best_addr;
300
// Generic POSIX variant.
301
bool get_local_address(sa_family_t family, rak::socket_address *address) {
303
if (!sock.open_datagram()) {
307
rak::socket_address dummy_dest;
311
case rak::socket_address::af_inet:
312
dummy_dest.set_address_c_str("4.0.0.0");
315
case rak::socket_address::af_inet6:
316
dummy_dest.set_address_c_str("2001:700::");
320
throw internal_error("Unknown address family");
322
dummy_dest.set_port(80);
324
if (!sock.connect(dummy_dest)) {
329
bool ret = sock.getsockname(address);