Ticket #1111: libtorrent-0.12.7-ipv6-08.patch
| File libtorrent-0.12.7-ipv6-08.patch, 40.3 KB (added by anonymous, 13 months ago) |
|---|
-
rak/socket_address.h
diff -Nur libtorrent-0.12.7.orig/rak/socket_address.h libtorrent-0.12.7/rak/socket_address.h
old new 145 145 }; 146 146 }; 147 147 148 // Reme ber to set the AF_INET.148 // Remember to set the AF_INET. 149 149 150 150 class socket_address_inet { 151 151 public: … … 184 184 185 185 const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&m_sockaddr); } 186 186 const sockaddr_in* c_sockaddr_inet() const { return &m_sockaddr; } 187 188 #ifdef RAK_USE_INET6 189 socket_address_inet6 to_mapped_address() const; 190 #endif 187 191 188 192 bool operator == (const socket_address_inet& rhs) const; 189 193 bool operator < (const socket_address_inet& rhs) const; … … 192 196 struct sockaddr_in m_sockaddr; 193 197 }; 194 198 199 #ifdef RAK_USE_INET6 200 // Remember to set the AF_INET6. 201 202 class socket_address_inet6 { 203 public: 204 bool is_any() const { return is_port_any() && is_address_any(); } 205 bool is_valid() const { return !is_port_any() && !is_address_any(); } 206 bool is_port_any() const { return port() == 0; } 207 bool is_address_any() const { return std::memcmp(&m_sockaddr.sin6_addr, &in6addr_any, sizeof(in6_addr)) == 0; } 208 209 void clear() { std::memset(this, 0, sizeof(socket_address_inet6)); set_family(); } 210 211 uint16_t port() const { return ntohs(m_sockaddr.sin6_port); } 212 uint16_t port_n() const { return m_sockaddr.sin6_port; } 213 void set_port(uint16_t p) { m_sockaddr.sin6_port = htons(p); } 214 void set_port_n(uint16_t p) { m_sockaddr.sin6_port = p; } 215 216 in6_addr address() const { return m_sockaddr.sin6_addr; } 217 std::string address_str() const; 218 bool address_c_str(char* buf, socklen_t size) const; 219 220 void set_address(in6_addr a) { m_sockaddr.sin6_addr = a; } 221 bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); } 222 bool set_address_c_str(const char* a); 223 224 void set_address_any() { set_port(0); set_address(in6addr_any); } 225 226 sa_family_t family() const { return m_sockaddr.sin6_family; } 227 void set_family() { m_sockaddr.sin6_family = AF_INET6; } 228 229 sockaddr* c_sockaddr() { return reinterpret_cast<sockaddr*>(&m_sockaddr); } 230 sockaddr_in6* c_sockaddr_inet6() { return &m_sockaddr; } 231 232 const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&m_sockaddr); } 233 const sockaddr_in6* c_sockaddr_inet6() const { return &m_sockaddr; } 234 235 socket_address normalize_address() const; 236 237 bool operator == (const socket_address_inet6& rhs) const; 238 bool operator < (const socket_address_inet6& rhs) const; 239 240 private: 241 struct sockaddr_in6 m_sockaddr; 242 }; 243 #endif 244 195 245 // Unique key for the address, excluding port numbers etc. 196 246 class socket_address_key { 197 247 public: … … 241 291 switch (family()) { 242 292 case af_inet: 243 293 return sa_inet()->is_valid(); 244 // case af_inet6: 245 // return sa_inet6().is_valid(); 294 #ifdef RAK_USE_INET6 295 case af_inet6: 296 return sa_inet6()->is_valid(); 297 #endif 246 298 default: 247 299 return false; 248 300 } … … 253 305 switch (family()) { 254 306 case af_inet: 255 307 return !sa_inet()->is_address_any(); 308 #ifdef RAK_USE_INET6 309 case af_inet6: 310 return !sa_inet6()->is_address_any(); 311 #endif 256 312 default: 257 313 return false; 258 314 } … … 263 319 switch (family()) { 264 320 case af_inet: 265 321 return sa_inet()->is_address_any(); 322 #ifdef RAK_USE_INET6 323 case af_inet6: 324 return sa_inet6()->is_address_any(); 325 #endif 266 326 default: 267 327 return true; 268 328 } … … 273 333 switch (family()) { 274 334 case af_inet: 275 335 return sa_inet()->port(); 336 #ifdef RAK_USE_INET6 337 case af_inet6: 338 return sa_inet6()->port(); 339 #endif 276 340 default: 277 341 return 0; 278 342 } … … 283 347 switch (family()) { 284 348 case af_inet: 285 349 return sa_inet()->set_port(p); 350 #ifdef RAK_USE_INET6 351 case af_inet6: 352 return sa_inet6()->set_port(p); 353 #endif 286 354 default: 287 355 break; 288 356 } … … 293 361 switch (family()) { 294 362 case af_inet: 295 363 return sa_inet()->address_str(); 364 #ifdef RAK_USE_INET6 365 case af_inet6: 366 return sa_inet6()->address_str(); 367 #endif 296 368 default: 297 369 return std::string(); 298 370 } … … 303 375 switch (family()) { 304 376 case af_inet: 305 377 return sa_inet()->address_c_str(buf, size); 378 #ifdef RAK_USE_INET6 379 case af_inet6: 380 return sa_inet6()->address_c_str(buf, size); 381 #endif 306 382 default: 307 383 return false; 308 384 } … … 314 390 sa_inet()->set_family(); 315 391 return true; 316 392 393 #ifdef RAK_USE_INET6 394 } else if (sa_inet6()->set_address_c_str(a)) { 395 sa_inet6()->set_family(); 396 return true; 397 #endif 398 317 399 } else { 318 400 return false; 319 401 } … … 325 407 switch(family()) { 326 408 case af_inet: 327 409 return sizeof(sockaddr_in); 410 #ifdef RAK_USE_INET6 411 case af_inet6: 412 return sizeof(sockaddr_in6); 413 #endif 328 414 default: 329 415 return 0; 330 416 } … … 349 435 switch (family()) { 350 436 case af_inet: 351 437 return *sa_inet() == *rhs.sa_inet(); 352 // case af_inet6: 353 // return *sa_inet6() == *rhs.sa_inet6(); 438 #ifdef RAK_USE_INET6 439 case af_inet6: 440 return *sa_inet6() == *rhs.sa_inet6(); 441 #endif 354 442 default: 355 443 throw std::logic_error("socket_address::operator == (rhs) invalid type comparison."); 356 444 } … … 364 452 switch (family()) { 365 453 case af_inet: 366 454 return *sa_inet() < *rhs.sa_inet(); 367 // case af_inet6: 368 // return *sa_inet6() < *rhs.sa_inet6(); 455 #ifdef RAK_USE_INET6 456 case af_inet6: 457 return *sa_inet6() < *rhs.sa_inet6(); 458 #endif 369 459 default: 370 460 throw std::logic_error("socket_address::operator < (rhs) invalid type comparison."); 371 461 } … … 391 481 return inet_pton(AF_INET, a, &m_sockaddr.sin_addr); 392 482 } 393 483 484 #ifdef RAK_USE_INET6 485 inline socket_address_inet6 486 socket_address_inet::to_mapped_address() const { 487 uint32_t addr32[4]; 488 addr32[0] = 0; 489 addr32[1] = 0; 490 addr32[2] = htonl(0xffff); 491 addr32[3] = m_sockaddr.sin_addr.s_addr; 492 493 socket_address_inet6 sa; 494 sa.clear(); 495 sa.set_address(*reinterpret_cast<in6_addr *>(addr32)); 496 sa.set_port_n(m_sockaddr.sin_port); 497 return sa; 498 } 499 #endif 500 394 501 inline bool 395 502 socket_address_inet::operator == (const socket_address_inet& rhs) const { 396 503 return … … 406 513 m_sockaddr.sin_port < rhs.m_sockaddr.sin_port); 407 514 } 408 515 516 #ifdef RAK_USE_INET6 517 518 inline std::string 519 socket_address_inet6::address_str() const { 520 char buf[INET6_ADDRSTRLEN]; 521 522 if (!address_c_str(buf, INET6_ADDRSTRLEN)) 523 return std::string(); 524 525 return std::string(buf); 526 } 527 528 inline bool 529 socket_address_inet6::address_c_str(char* buf, socklen_t size) const { 530 return inet_ntop(family(), &m_sockaddr.sin6_addr, buf, size); 531 } 532 533 inline bool 534 socket_address_inet6::set_address_c_str(const char* a) { 535 return inet_pton(AF_INET6, a, &m_sockaddr.sin6_addr); 536 } 537 538 inline socket_address 539 socket_address_inet6::normalize_address() const { 540 const uint32_t *addr32 = reinterpret_cast<const uint32_t *>(m_sockaddr.sin6_addr.s6_addr); 541 if (addr32[0] == 0 && addr32[1] == 0 && addr32[2] == htonl(0xffff)) { 542 socket_address addr4; 543 addr4.sa_inet()->set_family(); 544 addr4.sa_inet()->set_address_n(addr32[3]); 545 addr4.sa_inet()->set_port_n(m_sockaddr.sin6_port); 546 return addr4; 547 } 548 return *reinterpret_cast<const socket_address*>(this); 549 } 550 551 inline bool 552 socket_address_inet6::operator == (const socket_address_inet6& rhs) const { 553 return 554 memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr)) == 0 && 555 m_sockaddr.sin6_port == rhs.m_sockaddr.sin6_port; 556 } 557 558 inline bool 559 socket_address_inet6::operator < (const socket_address_inet6& rhs) const { 560 int addr_comp = memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr)); 561 return 562 addr_comp < 0 || 563 (addr_comp == 0 || 564 m_sockaddr.sin6_port < rhs.m_sockaddr.sin6_port); 565 } 566 567 #endif 568 409 569 } 410 570 411 571 #endif -
src/dht/dht_server.cc
@@ -54,8 +54,15@@ m_recentlyInactive(0), m_bucket(NULL) { +#ifdef RAK_USE_INET6 + if (sa->family() != rak::socket_address::af_inet && + (sa->family() != rak::socket_address::af_inet6 || + !sa->sa_inet6()->is_any())) + throw resource_error("Addres not af_inet or in6addr_any"); +#else if (sa->family() != rak::socket_address::af_inet) throw resource_error("Address not af_inet"); +#endif } DhtNode::DhtNode(const std::string& id, const Object& cache) : @@ -84,8 +91,20 @@ Object* DhtNode::store_cache(Object* container) const { - container->insert_key("i", m_socketAddress.sa_inet()->address_h()); - container->insert_key("p", m_socketAddress.sa_inet()->port()); +#ifdef RAK_USE_INET6 + if (m_socketAddress.family() == rak::socket_address::af_inet6) { + // Currently, all we support is in6addr_any (checked in the constructor), + // which is effectively equivalent to this. Note that we need to specify + // int64_t explicitly here because a zero constant is special in C++ and + // thus we need an explicit match. + container->insert_key("i", int64_t(0)); + container->insert_key("p", m_socketAddress.sa_inet6()->port()); + } else +#endif + { + container->insert_key("i", m_socketAddress.sa_inet()->address_h()); + container->insert_key("p", m_socketAddress.sa_inet()->port()); + } container->insert_key("t", m_lastSeen); return container; } diff -Nur libtorrent-0.12.7.orig/src/dht/dht_server.cc libtorrent-0.12.7/src/dht/dht_server.ccold new 700 700 if (read < 0) 701 701 break; 702 702 703 #ifdef RAK_USE_INET6 704 // We can currently only process mapped-IPv4 addresses, not real IPv6. 705 // Translate them to an af_inet socket_address. 706 if (sa.family() == rak::socket_address::af_inet6) 707 sa = sa.sa_inet6()->normalize_address(); 708 #endif 709 710 if (sa.family() != rak::socket_address::af_inet) 711 continue; 712 703 713 total += read; 704 714 705 715 // If it's not a valid bencode dictionary at all, it's probably not a DHT -
src/net/address_list.h
diff -Nur libtorrent-0.12.7.orig/src/net/address_list.h libtorrent-0.12.7/src/net/address_list.h
old new 54 54 55 55 void parse_address_compact(raw_string s); 56 56 void parse_address_compact(const std::string& s); 57 #ifdef RAK_USE_INET6 58 void parse_address_compact_ipv6(const std::string& s); 59 #endif 57 60 58 61 private: 59 62 static rak::socket_address parse_address(const Object& b); … … 99 99 const char* c_str() const { return reinterpret_cast<const char*>(this); } 100 100 } __attribute__ ((packed)); 101 101 102 #ifdef RAK_USE_INET6 103 struct SocketAddressCompact6 { 104 SocketAddressCompact6() {} 105 SocketAddressCompact6(in6_addr a, uint16_t p) : addr(a), port(p) {} 106 SocketAddressCompact6(const rak::socket_address_inet6* sa) : addr(sa->address()), port(sa->port_n()) {} 107 108 operator rak::socket_address () const { 109 rak::socket_address sa; 110 sa.sa_inet6()->clear(); 111 sa.sa_inet6()->set_port_n(port); 112 sa.sa_inet6()->set_address(addr); 113 114 return sa; 115 } 116 117 in6_addr addr; 118 uint16_t port; 119 120 const char* c_str() const { return reinterpret_cast<const char*>(this); } 121 } __attribute__ ((packed)); 122 #endif 123 102 124 } 103 125 104 126 #endif -
src/net/address_list.cc
diff -Nur libtorrent-0.12.7.orig/src/net/address_list.cc libtorrent-0.12.7/src/net/address_list.cc
old new 77 77 std::back_inserter(*this)); 78 78 } 79 79 80 #ifdef RAK_USE_INET6 81 void 82 AddressList::parse_address_compact_ipv6(const std::string& s) { 83 if (sizeof(const SocketAddressCompact6) != 18) 84 throw internal_error("ConnectionList::AddressList::parse_address_compact_ipv6(...) bad struct size."); 85 86 std::copy(reinterpret_cast<const SocketAddressCompact6*>(s.c_str()), 87 reinterpret_cast<const SocketAddressCompact6*>(s.c_str() + s.size() - s.size() % sizeof(SocketAddressCompact6)), 88 std::back_inserter(*this)); 89 } 90 #endif 91 80 92 void 81 93 AddressList::parse_address_bencode(raw_list s) { 82 94 if (sizeof(const SocketAddressCompact) != 6) -
src/net/local_addr.cc
diff -Nur libtorrent-0.12.7.orig/src/net/local_addr.cc libtorrent-0.12.7/src/net/local_addr.cc
old new 1 // libTorrent - BitTorrent library 2 // Copyright (C) 2005-2007, Jari Sundell 3 // 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. 8 // 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. 13 // 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 17 // 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 22 // including the two. 23 // 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. 31 // 32 // Contact: Jari Sundell <jaris@ifi.uio.no> 33 // 34 // Skomakerveien 33 35 // 3185 Skoppum, NORWAY 36 37 #include "config.h" 38 39 #include <stdio.h> 40 #include <ifaddrs.h> 41 #include <rak/socket_address.h> 42 #include <sys/types.h> 43 #include <errno.h> 44 45 #ifdef __linux__ 46 #include <linux/netlink.h> 47 #include <linux/rtnetlink.h> 48 #endif 49 50 #include "torrent/exceptions.h" 51 #include "socket_fd.h" 52 #include "local_addr.h" 53 54 namespace torrent { 55 namespace { 56 57 // IPv4 priority, from highest to lowest: 58 // 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)) { 66 return 5; 67 } 68 if (addr.s_addr == htonl(0)) { 69 return 4; 70 } 71 if ((addr.s_addr & htonl(0xffff0000U)) == htonl(0xa9fe0000U)) { 72 return 3; 73 } 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)) { 77 return 2; 78 } 79 return 1; 80 } 81 82 #ifdef RAK_USE_INET6 83 // IPv6 priority, from highest to lowest: 84 // 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)) { 96 return 4; 97 } 98 if (addr32[0] == htonl(0x20010000)) { 99 return 3; 100 } 101 if ((addr32[0] & htonl(0xffff0000)) == htonl(0x20020000)) { 102 return 2; 103 } 104 if ((addr32[0] & htonl(0xe0000000)) == htonl(0x20000000)) { 105 return 1; 106 } 107 return 5; 108 } 109 #endif 110 111 int get_priority(const rak::socket_address& addr) { 112 switch (addr.family()) { 113 case AF_INET: 114 return get_priority_ipv4(addr.c_sockaddr_inet()->sin_addr); 115 #ifdef RAK_USE_INET6 116 case AF_INET6: 117 return get_priority_ipv6(addr.c_sockaddr_inet6()->sin6_addr); 118 #endif 119 default: 120 throw torrent::internal_error("Unknown address family given to compare"); 121 } 122 } 123 124 } 125 126 #ifdef __linux__ 127 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) { 131 ifaddrs *ifaddrs; 132 if (getifaddrs(&ifaddrs)) { 133 return false; 134 } 135 136 rak::socket_address best_addr; 137 switch (family) { 138 case AF_INET: 139 best_addr.sa_inet()->clear(); 140 break; 141 #ifdef RAK_USE_INET6 142 case AF_INET6: 143 best_addr.sa_inet6()->clear(); 144 break; 145 #endif 146 default: 147 throw torrent::internal_error("Unknown address family given to get_local_address"); 148 } 149 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; 154 155 // Get all the addresses via Linux' netlink interface. 156 int fd = ::socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 157 if (fd == -1) { 158 return false; 159 } 160 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))) { 165 ::close(fd); 166 return false; 167 } 168 169 const int seq_no = 1; 170 struct { 171 nlmsghdr nh; 172 rtgenmsg g; 173 } req; 174 memset(&req, 0, sizeof(req)); 175 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; 182 183 int ret; 184 do { 185 ret = ::sendto(fd, &req, sizeof(req), 0, (sockaddr *)&nladdr, sizeof(nladdr)); 186 } while (ret == -1 && errno == EINTR); 187 188 if (ret == -1) { 189 ::close(fd); 190 return false; 191 } 192 193 bool done = false; 194 do { 195 char buf[4096]; 196 socklen_t len = sizeof(nladdr); 197 do { 198 ret = ::recvfrom(fd, buf, sizeof(buf), 0, (sockaddr *)&nladdr, &len); 199 } while (ret == -1 && errno == EINTR); 200 201 if (ret < 0) { 202 ::close(fd); 203 return false; 204 } 205 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) 210 continue; 211 if (nlmsg->nlmsg_type == NLMSG_DONE) { 212 done = true; 213 break; 214 } 215 if (nlmsg->nlmsg_type == NLMSG_ERROR) { 216 ::close(fd); 217 return false; 218 } 219 if (nlmsg->nlmsg_type != RTM_NEWADDR) 220 continue; 221 222 const ifaddrmsg *ifa = (const ifaddrmsg *)NLMSG_DATA(nlmsg); 223 224 if (ifa->ifa_family != family) 225 continue; 226 227 #ifdef IFA_F_OPTIMISTIC 228 if ((ifa->ifa_flags & IFA_F_OPTIMISTIC) != 0) 229 continue; 230 #endif 231 #ifdef IFA_F_DADFAILED 232 if ((ifa->ifa_flags & IFA_F_DADFAILED) != 0) 233 continue; 234 #endif 235 #ifdef IFA_F_DEPRECATED 236 if ((ifa->ifa_flags & IFA_F_DEPRECATED) != 0) 237 continue; 238 #endif 239 #ifdef IFA_F_TENTATIVE 240 if ((ifa->ifa_flags & IFA_F_TENTATIVE) != 0) 241 continue; 242 #endif 243 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); 251 RTA_OK(rta, plen); 252 rta = RTA_NEXT(rta, plen)) { 253 if (rta->rta_type != IFA_LOCAL && 254 rta->rta_type != IFA_ADDRESS) { 255 continue; 256 } 257 if (rta->rta_type == IFA_ADDRESS && seen_addr) { 258 continue; 259 } 260 seen_addr = true; 261 switch (ifa->ifa_family) { 262 case AF_INET: 263 this_addr.sa_inet()->clear(); 264 this_addr.sa_inet()->set_address(*(const in_addr *)RTA_DATA(rta)); 265 break; 266 #ifdef RAK_USE_INET6 267 case AF_INET6: 268 this_addr.sa_inet6()->clear(); 269 this_addr.sa_inet6()->set_address(*(const in6_addr *)RTA_DATA(rta)); 270 break; 271 #endif 272 } 273 } 274 if (!seen_addr) 275 continue; 276 277 int this_addr_pri = get_priority(this_addr) * 2; 278 if ((ifa->ifa_flags & IFA_F_SECONDARY) == IFA_F_SECONDARY) { 279 ++this_addr_pri; 280 } 281 282 if (this_addr_pri < best_addr_pri) { 283 best_addr = this_addr; 284 best_addr_pri = this_addr_pri; 285 } 286 } 287 } while (!done); 288 289 ::close(fd); 290 if (!best_addr.is_address_any()) { 291 *address = best_addr; 292 return true; 293 } else { 294 return false; 295 } 296 } 297 298 #else 299 300 // Generic POSIX variant. 301 bool get_local_address(sa_family_t family, rak::socket_address *address) { 302 SocketFd sock; 303 if (!sock.open_datagram()) { 304 return false; 305 } 306 307 rak::socket_address dummy_dest; 308 dummy_dest.clear(); 309 310 switch (family) { 311 case rak::socket_address::af_inet: 312 dummy_dest.set_address_c_str("4.0.0.0"); 313 break; 314 #ifdef RAK_USE_INET6 315 case rak::socket_address::af_inet6: 316 dummy_dest.set_address_c_str("2001:700::"); 317 break; 318 #endif 319 default: 320 throw internal_error("Unknown address family"); 321 } 322 dummy_dest.set_port(80); 323 324 if (!sock.connect(dummy_dest)) { 325 sock.close(); 326 return false; 327 } 328 329 bool ret = sock.getsockname(address); 330 sock.close(); 331 return ret; 332 } 333 334 #endif 335 336 } -
src/net/local_addr.h
diff -Nur libtorrent-0.12.7.orig/src/net/local_addr.h libtorrent-0.12.7/src/net/local_addr.h
old new 1 // libTorrent - BitTorrent library 2 // Copyright (C) 2005-2007, Jari Sundell 3 // 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. 8 // 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. 13 // 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 17 // 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 22 // including the two. 23 // 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. 31 // 32 // Contact: Jari Sundell <jaris@ifi.uio.no> 33 // 34 // Skomakerveien 33 35 // 3185 Skoppum, NORWAY 36 37 // A routine to get a local IP address that can be presented to a tracker. 38 // (Does not use UPnP etc., so will not understand NAT.) 39 // On a machine with multiple network cards, address selection can be a 40 // complex process, and in general what's selected is a source/destination 41 // address pair. However, this routine will give an approximation that will 42 // be good enough for most purposes and users. 43 44 #ifndef LIBTORRENT_NET_LOCAL_ADDR_H 45 #define LIBTORRENT_NET_LOCAL_ADDR_H 46 47 #include <unistd.h> 48 49 namespace rak { 50 class socket_address; 51 } 52 53 namespace torrent { 54 55 // Note: family must currently be rak::af_inet or rak::af_inet6 56 // (rak::af_unspec won't do); anything else will throw an exception. 57 // Returns false if no address of the given family could be found, 58 // either because there are none, or because something went wrong in 59 // the process (e.g., no free file descriptors). 60 bool get_local_address(sa_family_t family, rak::socket_address *address); 61 62 } 63 64 #endif /* LIBTORRENT_NET_LOCAL_ADDR_H */ -
src/net/Makefile.am
diff -Nur libtorrent-0.12.7.orig/src/net/Makefile.am libtorrent-0.12.7/src/net/Makefile.am
old new 4 4 address_list.cc \ 5 5 address_list.h \ 6 6 data_buffer.h \ 7 local_addr.cc \ 8 local_addr.h \ 7 9 listen.cc \ 8 10 listen.h \ 9 11 protocol_buffer.h \ -
src/net/Makefile.in
diff -Nur libtorrent-0.12.7.orig/src/net/Makefile.in libtorrent-0.12.7/src/net/Makefile.in
old new 54 54 CONFIG_CLEAN_VPATH_FILES = 55 55 LTLIBRARIES = $(noinst_LTLIBRARIES) 56 56 libsub_net_la_LIBADD = 57 am_libsub_net_la_OBJECTS = address_list.lo l isten.lo socket_base.lo \58 socket_ datagram.lo socket_fd.lo socket_set.lo socket_stream.lo \59 throttle_internal.lo throttle_list.lo57 am_libsub_net_la_OBJECTS = address_list.lo local_addr.lo listen.lo \ 58 socket_base.lo socket_datagram.lo socket_fd.lo socket_set.lo \ 59 socket_stream.lo throttle_internal.lo throttle_list.lo 60 60 libsub_net_la_OBJECTS = $(am_libsub_net_la_OBJECTS) 61 61 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) 62 62 depcomp = $(SHELL) $(top_srcdir)/depcomp … … 220 220 address_list.cc \ 221 221 address_list.h \ 222 222 data_buffer.h \ 223 local_addr.cc \ 224 local_addr.h \ 223 225 listen.cc \ 224 226 listen.h \ 225 227 protocol_buffer.h \ … … 294 296 295 297 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/address_list.Plo@am__quote@ 296 298 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/listen.Plo@am__quote@ 299 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/local_addr.Plo@am__quote@ 297 300 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_base.Plo@am__quote@ 298 301 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_datagram.Plo@am__quote@ 299 302 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_fd.Plo@am__quote@ -
src/net/socket_datagram.cc
diff -Nur libtorrent-0.12.7.orig/src/net/socket_datagram.cc libtorrent-0.12.7/src/net/socket_datagram.cc
old new 73 73 int r; 74 74 75 75 if (sa != NULL) { 76 r = ::sendto(m_fileDesc, buffer, length, 0, sa->sa_inet()->c_sockaddr(), sizeof(rak::socket_address_inet)); 76 #ifdef RAK_USE_INET6 77 if (m_ipv6_socket && sa->family() == rak::socket_address::pf_inet) { 78 rak::socket_address_inet6 sa_mapped = sa->sa_inet()->to_mapped_address(); 79 r = ::sendto(m_fileDesc, buffer, length, 0, sa_mapped.c_sockaddr(), sizeof(rak::socket_address_inet6)); 80 } else 81 #endif 82 r = ::sendto(m_fileDesc, buffer, length, 0, sa->c_sockaddr(), sa->length()); 77 83 } else { 78 84 r = ::send(m_fileDesc, buffer, length, 0); 79 85 } -
src/net/socket_fd.cc
diff -Nur libtorrent-0.12.7.orig/src/net/socket_fd.cc libtorrent-0.12.7/src/net/socket_fd.cc
old new 70 70 check_valid(); 71 71 int opt = p; 72 72 73 #ifdef RAK_USE_INET6 74 if (m_ipv6_socket) 75 return setsockopt(m_fd, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) == 0; 76 else 77 #endif 73 78 return setsockopt(m_fd, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) == 0; 74 79 } 75 80 … … 112 117 113 118 bool 114 119 SocketFd::open_stream() { 120 #ifdef RAK_USE_INET6 121 m_fd = socket(rak::socket_address::pf_inet6, SOCK_STREAM, IPPROTO_TCP); 122 if (m_fd == -1) { 123 m_ipv6_socket = false; 124 return (m_fd = socket(rak::socket_address::pf_inet, SOCK_STREAM, IPPROTO_TCP)) != -1; 125 } 126 m_ipv6_socket = true; 127 128 int zero = 0; 129 return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1; 130 #else 115 131 return (m_fd = socket(rak::socket_address::pf_inet, SOCK_STREAM, IPPROTO_TCP)) != -1; 132 #endif 116 133 } 117 134 118 135 bool 119 136 SocketFd::open_datagram() { 137 #ifdef RAK_USE_INET6 138 m_fd = socket(rak::socket_address::pf_inet6, SOCK_DGRAM, 0); 139 if (m_fd == -1) { 140 m_ipv6_socket = false; 141 return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1; 142 } 143 m_ipv6_socket = true; 144 145 int zero = 0; 146 return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1; 147 #else 120 148 return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1; 149 #endif 121 150 } 122 151 123 152 bool … … 135 164 SocketFd::bind(const rak::socket_address& sa) { 136 165 check_valid(); 137 166 167 #ifdef RAK_USE_INET6 168 if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) { 169 rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address(); 170 return !::bind(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped)); 171 } 172 #endif 138 173 return !::bind(m_fd, sa.c_sockaddr(), sa.length()); 139 174 } 140 175 … … 142 177 SocketFd::bind(const rak::socket_address& sa, unsigned int length) { 143 178 check_valid(); 144 179 180 #ifdef RAK_USE_INET6 181 if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) { 182 rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address(); 183 return !::bind(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped)); 184 } 185 #endif 145 186 return !::bind(m_fd, sa.c_sockaddr(), length); 146 187 } 147 188 … … 149 190 SocketFd::connect(const rak::socket_address& sa) { 150 191 check_valid(); 151 192 193 #ifdef RAK_USE_INET6 194 if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) { 195 rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address(); 196 return !::connect(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped)) || errno == EINPROGRESS; 197 } 198 #endif 152 199 return !::connect(m_fd, sa.c_sockaddr(), sa.length()) || errno == EINPROGRESS; 153 200 } 154 201 155 202 bool 203 SocketFd::getsockname(rak::socket_address *sa) { 204 check_valid(); 205 206 socklen_t len = sizeof(rak::socket_address); 207 if (::getsockname(m_fd, sa->c_sockaddr(), &len)) { 208 return false; 209 } 210 211 #ifdef RAK_USE_INET6 212 if (m_ipv6_socket && sa->family() == rak::socket_address::af_inet6) { 213 *sa = sa->sa_inet6()->normalize_address(); 214 } 215 #endif 216 217 return true; 218 } 219 220 bool 156 221 SocketFd::listen(int size) { 157 222 check_valid(); 158 223 … … 164 229 check_valid(); 165 230 socklen_t len = sizeof(rak::socket_address); 166 231 232 #ifdef RAK_USE_INET6 233 if (sa == NULL) { 234 return SocketFd(::accept(m_fd, NULL, &len)); 235 } 236 int fd = ::accept(m_fd, sa->c_sockaddr(), &len); 237 if (fd != -1 && m_ipv6_socket && sa->family() == rak::socket_address::af_inet6) { 238 *sa = sa->sa_inet6()->normalize_address(); 239 } 240 return SocketFd(fd); 241 #else 167 242 return SocketFd(::accept(m_fd, sa != NULL ? sa->c_sockaddr() : NULL, &len)); 243 #endif 168 244 } 169 245 170 246 // unsigned int -
src/net/socket_fd.h
diff -Nur libtorrent-0.12.7.orig/src/net/socket_fd.h libtorrent-0.12.7/src/net/socket_fd.h
old new 77 77 bool bind(const rak::socket_address& sa); 78 78 bool bind(const rak::socket_address& sa, unsigned int length); 79 79 bool connect(const rak::socket_address& sa); 80 bool getsockname(rak::socket_address* sa); 80 81 81 82 bool listen(int size); 82 83 SocketFd accept(rak::socket_address* sa); … … 88 89 inline void check_valid() const; 89 90 90 91 int m_fd; 92 #ifdef RAK_USE_INET6 93 bool m_ipv6_socket; 94 #endif 91 95 }; 92 96 93 97 } -
src/torrent/connection_manager.cc
diff -Nur libtorrent-0.12.7.orig/src/torrent/connection_manager.cc libtorrent-0.12.7/src/torrent/connection_manager.cc
old new 80 80 m_slotResolver(&resolve_host) { 81 81 82 82 m_bindAddress = (new rak::socket_address())->c_sockaddr(); 83 rak::socket_address::cast_from(m_bindAddress)->sa_inet()->clear();84 85 83 m_localAddress = (new rak::socket_address())->c_sockaddr(); 86 rak::socket_address::cast_from(m_localAddress)->sa_inet()->clear();87 88 84 m_proxyAddress = (new rak::socket_address())->c_sockaddr(); 85 86 #ifdef RAK_USE_INET6 87 rak::socket_address::cast_from(m_bindAddress)->sa_inet6()->clear(); 88 rak::socket_address::cast_from(m_localAddress)->sa_inet6()->clear(); 89 rak::socket_address::cast_from(m_proxyAddress)->sa_inet6()->clear(); 90 #else 91 rak::socket_address::cast_from(m_bindAddress)->sa_inet()->clear(); 92 rak::socket_address::cast_from(m_localAddress)->sa_inet()->clear(); 89 93 rak::socket_address::cast_from(m_proxyAddress)->sa_inet()->clear(); 94 #endif 90 95 } 91 96 92 97 ConnectionManager::~ConnectionManager() { … … 125 130 ConnectionManager::set_bind_address(const sockaddr* sa) { 126 131 const rak::socket_address* rsa = rak::socket_address::cast_from(sa); 127 132 133 #ifndef RAK_USE_INET6 128 134 if (rsa->family() != rak::socket_address::af_inet) 129 135 throw input_error("Tried to set a bind address that is not an af_inet address."); 136 #endif 130 137 131 138 rak::socket_address::cast_from(m_bindAddress)->copy(*rsa, rsa->length()); 132 139 } … … 135 142 ConnectionManager::set_local_address(const sockaddr* sa) { 136 143 const rak::socket_address* rsa = rak::socket_address::cast_from(sa); 137 144 145 #ifndef RAK_USE_INET6 138 146 if (rsa->family() != rak::socket_address::af_inet) 139 147 throw input_error("Tried to set a local address that is not an af_inet address."); 148 #endif 140 149 141 150 rak::socket_address::cast_from(m_localAddress)->copy(*rsa, rsa->length()); 142 151 } … … 145 154 ConnectionManager::set_proxy_address(const sockaddr* sa) { 146 155 const rak::socket_address* rsa = rak::socket_address::cast_from(sa); 147 156 157 #ifndef RAK_USE_INET6 148 158 if (rsa->family() != rak::socket_address::af_inet) 149 159 throw input_error("Tried to set a proxy address that is not an af_inet address."); 160 #endif 150 161 151 162 rak::socket_address::cast_from(m_proxyAddress)->copy(*rsa, rsa->length()); 152 163 } -
src/torrent/event.h
diff -Nur libtorrent-0.12.7.orig/src/torrent/event.h libtorrent-0.12.7/src/torrent/event.h
old new 57 57 58 58 protected: 59 59 int m_fileDesc; 60 61 #ifdef RAK_USE_INET6 62 bool m_ipv6_socket; 63 #endif 60 64 }; 61 65 62 66 } -
src/torrent/peer/peer_list.cc
diff -Nur libtorrent-0.12.7.orig/src/torrent/peer/peer_list.cc libtorrent-0.12.7/src/torrent/peer/peer_list.cc
old new 65 65 // humans. 66 66 return sa1->sa_inet()->address_h() < sa2->sa_inet()->address_h(); 67 67 68 #ifdef RAK_USE_INET6 69 else { 70 const in6_addr addr1 = sa1->sa_inet6()->address(); 71 const in6_addr addr2 = sa2->sa_inet6()->address(); 72 return memcmp(&addr1, &addr2, sizeof(in6_addr)) < 0; 73 } 74 #else 68 75 else 69 // When we implement INET6 handling, embed the ipv4 address in70 // the ipv6 address.71 76 throw internal_error("socket_address_key(...) tried to compare an invalid family type."); 77 #endif 78 72 79 } 73 80 74 81 inline bool 75 82 socket_address_key::is_comparable(const sockaddr* sa) { 76 return rak::socket_address::cast_from(sa)->family() == rak::socket_address::af_inet; 83 return rak::socket_address::cast_from(sa)->family() == rak::socket_address::af_inet || 84 rak::socket_address::cast_from(sa)->family() == rak::socket_address::af_inet6; 77 85 } 78 86 79 87 struct peer_list_equal_port : public std::binary_function<PeerList::reference, uint16_t, bool> { -
src/tracker/tracker_http.cc
diff -Nur libtorrent-0.12.7.orig/src/tracker/tracker_http.cc libtorrent-0.12.7/src/tracker/tracker_http.cc
old new 42 42 #include <rak/string_manip.h> 43 43 44 44 #include "net/address_list.h" 45 #include "net/local_addr.h" 45 46 #include "torrent/connection_manager.h" 46 47 #include "torrent/download_info.h" 47 48 #include "torrent/exceptions.h" … … 114 115 115 116 const rak::socket_address* localAddress = rak::socket_address::cast_from(manager->connection_manager()->local_address()); 116 117 117 if (localAddress->family() == rak::socket_address::af_inet && 118 !localAddress->sa_inet()->is_address_any()) 118 if (!localAddress->is_address_any()) 119 119 s << "&ip=" << localAddress->address_str(); 120 121 #ifdef RAK_USE_INET6 122 if (localAddress->is_address_any() || localAddress->family() != rak::socket_address::pf_inet6) { 123 rak::socket_address local_v6; 124 if (get_local_address(rak::socket_address::af_inet6, &local_v6)) 125 s << "&ipv6=" << rak::copy_escape_html(local_v6.address_str()); 126 } 127 #endif 120 128 121 129 if (info->is_compact()) 122 130 s << "&compact=1"; … … 220 228 221 229 AddressList l; 222 230 223 try { 224 // Due to some trackers sending the wrong type when no peers are 225 // available, don't bork on it. 226 if (b.get_key("peers").is_string()) 227 l.parse_address_compact(b.get_key_string("peers")); 231 if (!b.has_key("peers") 232 #ifdef RAK_USE_INET6 233 && !b.has_key("peers6") 234 #endif 235 ) { 236 return receive_failed("No peers returned"); 237 } 228 238 229 else if (b.get_key("peers").is_list()) 230 l.parse_address_normal(b.get_key_list("peers")); 239 if (b.has_key("peers")) { 240 try { 241 // Due to some trackers sending the wrong type when no peers are 242 // available, don't bork on it. 243 if (b.get_key("peers").is_string()) 244 l.parse_address_compact(b.get_key_string("peers")); 245 246 else if (b.get_key("peers").is_list()) 247 l.parse_address_normal(b.get_key_list("peers")); 248 249 } catch (bencode_error& e) { 250 return receive_failed(e.what()); 251 } 252 } 231 253 232 } catch (bencode_error& e) { 233 return receive_failed(e.what()); 254 #ifdef RAK_USE_INET6 255 if (b.has_key("peers6")) { 256 l.parse_address_compact_ipv6(b.get_key_string("peers6")); 234 257 } 258 #endif 235 259 236 260 close(); 237 261 m_parent->receive_success(this, &l); -
src/tracker/tracker_udp.cc
diff -Nur libtorrent-0.12.7.orig/src/tracker/tracker_udp.cc libtorrent-0.12.7/src/tracker/tracker_udp.cc
old new 273 273 274 274 const rak::socket_address* localAddress = rak::socket_address::cast_from(manager->connection_manager()->local_address()); 275 275 276 // This code assumes we're have a inet address. 276 #ifdef RAK_USE_INET6 277 uint32_t local_addr = 0; 278 if (localAddress->family() == rak::socket_address::af_inet) 279 local_addr = localAddress->sa_inet()->address_n(); 280 #else 277 281 if (localAddress->family() != rak::socket_address::af_inet) 278 282 throw internal_error("TrackerUdp::prepare_announce_input() info->local_address() not of family AF_INET."); 283 284 uint32_t local_addr = localAddress->sa_inet()->address_n(); 285 #endif 279 286 280 m_writeBuffer->write_32_n(local Address->sa_inet()->address_n());287 m_writeBuffer->write_32_n(local_addr); 281 288 m_writeBuffer->write_32(m_parent->key()); 282 289 m_writeBuffer->write_32(m_parent->numwant()); 283 290 m_writeBuffer->write_16(manager->connection_manager()->listen_port());
