1
Description: Implement IPv6 for libtorrent
2
Author: "Steinar H. Gunderson" <sesse@debian.org>
3
Reviewed-By: Rogério Theodoro de Brito <rbrito@ime.usp.br>
4
Last-Updated: 2011-03-20
6
--- a/rak/socket_address.h
7
+++ b/rak/socket_address.h
12
-// Remeber to set the AF_INET.
13
+// Remember to set the AF_INET.
15
class socket_address_inet {
19
const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&m_sockaddr); }
20
const sockaddr_in* c_sockaddr_inet() const { return &m_sockaddr; }
23
+ socket_address_inet6 to_mapped_address() const;
26
bool operator == (const socket_address_inet& rhs) const;
27
bool operator < (const socket_address_inet& rhs) const;
29
struct sockaddr_in m_sockaddr;
33
+// Remember to set the AF_INET6.
35
+class socket_address_inet6 {
37
+ bool is_any() const { return is_port_any() && is_address_any(); }
38
+ bool is_valid() const { return !is_port_any() && !is_address_any(); }
39
+ bool is_port_any() const { return port() == 0; }
40
+ bool is_address_any() const { return std::memcmp(&m_sockaddr.sin6_addr, &in6addr_any, sizeof(in6_addr)) == 0; }
42
+ void clear() { std::memset(this, 0, sizeof(socket_address_inet6)); set_family(); }
44
+ uint16_t port() const { return ntohs(m_sockaddr.sin6_port); }
45
+ uint16_t port_n() const { return m_sockaddr.sin6_port; }
46
+ void set_port(uint16_t p) { m_sockaddr.sin6_port = htons(p); }
47
+ void set_port_n(uint16_t p) { m_sockaddr.sin6_port = p; }
49
+ in6_addr address() const { return m_sockaddr.sin6_addr; }
50
+ std::string address_str() const;
51
+ bool address_c_str(char* buf, socklen_t size) const;
53
+ void set_address(in6_addr a) { m_sockaddr.sin6_addr = a; }
54
+ bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); }
55
+ bool set_address_c_str(const char* a);
57
+ void set_address_any() { set_port(0); set_address(in6addr_any); }
59
+ sa_family_t family() const { return m_sockaddr.sin6_family; }
60
+ void set_family() { m_sockaddr.sin6_family = AF_INET6; }
62
+ sockaddr* c_sockaddr() { return reinterpret_cast<sockaddr*>(&m_sockaddr); }
63
+ sockaddr_in6* c_sockaddr_inet6() { return &m_sockaddr; }
65
+ const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&m_sockaddr); }
66
+ const sockaddr_in6* c_sockaddr_inet6() const { return &m_sockaddr; }
68
+ socket_address normalize_address() const;
70
+ bool operator == (const socket_address_inet6& rhs) const;
71
+ bool operator < (const socket_address_inet6& rhs) const;
74
+ struct sockaddr_in6 m_sockaddr;
78
// Unique key for the address, excluding port numbers etc.
79
class socket_address_key {
84
return sa_inet()->is_valid();
86
-// return sa_inet6().is_valid();
89
+ return sa_inet6()->is_valid();
97
return !sa_inet()->is_address_any();
100
+ return !sa_inet6()->is_address_any();
108
return sa_inet()->is_address_any();
109
+#ifdef RAK_USE_INET6
111
+ return sa_inet6()->is_address_any();
119
return sa_inet()->port();
120
+#ifdef RAK_USE_INET6
122
+ return sa_inet6()->port();
130
return sa_inet()->set_port(p);
131
+#ifdef RAK_USE_INET6
133
+ return sa_inet6()->set_port(p);
141
return sa_inet()->address_str();
142
+#ifdef RAK_USE_INET6
144
+ return sa_inet6()->address_str();
147
return std::string();
152
return sa_inet()->address_c_str(buf, size);
153
+#ifdef RAK_USE_INET6
155
+ return sa_inet6()->address_c_str(buf, size);
161
sa_inet()->set_family();
164
+#ifdef RAK_USE_INET6
165
+ } else if (sa_inet6()->set_address_c_str(a)) {
166
+ sa_inet6()->set_family();
176
return sizeof(sockaddr_in);
177
+#ifdef RAK_USE_INET6
179
+ return sizeof(sockaddr_in6);
187
return *sa_inet() == *rhs.sa_inet();
189
-// return *sa_inet6() == *rhs.sa_inet6();
190
+#ifdef RAK_USE_INET6
192
+ return *sa_inet6() == *rhs.sa_inet6();
195
throw std::logic_error("socket_address::operator == (rhs) invalid type comparison.");
200
return *sa_inet() < *rhs.sa_inet();
202
-// return *sa_inet6() < *rhs.sa_inet6();
203
+#ifdef RAK_USE_INET6
205
+ return *sa_inet6() < *rhs.sa_inet6();
208
throw std::logic_error("socket_address::operator < (rhs) invalid type comparison.");
211
return inet_pton(AF_INET, a, &m_sockaddr.sin_addr);
214
+#ifdef RAK_USE_INET6
215
+inline socket_address_inet6
216
+socket_address_inet::to_mapped_address() const {
217
+ uint32_t addr32[4];
220
+ addr32[2] = htonl(0xffff);
221
+ addr32[3] = m_sockaddr.sin_addr.s_addr;
223
+ socket_address_inet6 sa;
225
+ sa.set_address(*reinterpret_cast<in6_addr *>(addr32));
226
+ sa.set_port_n(m_sockaddr.sin_port);
232
socket_address_inet::operator == (const socket_address_inet& rhs) const {
235
m_sockaddr.sin_port < rhs.m_sockaddr.sin_port);
238
+#ifdef RAK_USE_INET6
241
+socket_address_inet6::address_str() const {
242
+ char buf[INET6_ADDRSTRLEN];
244
+ if (!address_c_str(buf, INET6_ADDRSTRLEN))
245
+ return std::string();
247
+ return std::string(buf);
251
+socket_address_inet6::address_c_str(char* buf, socklen_t size) const {
252
+ return inet_ntop(family(), &m_sockaddr.sin6_addr, buf, size);
256
+socket_address_inet6::set_address_c_str(const char* a) {
257
+ return inet_pton(AF_INET6, a, &m_sockaddr.sin6_addr);
260
+inline socket_address
261
+socket_address_inet6::normalize_address() const {
262
+ const uint32_t *addr32 = reinterpret_cast<const uint32_t *>(m_sockaddr.sin6_addr.s6_addr);
263
+ if (addr32[0] == 0 && addr32[1] == 0 && addr32[2] == htonl(0xffff)) {
264
+ socket_address addr4;
265
+ addr4.sa_inet()->set_family();
266
+ addr4.sa_inet()->set_address_n(addr32[3]);
267
+ addr4.sa_inet()->set_port_n(m_sockaddr.sin6_port);
270
+ return *reinterpret_cast<const socket_address*>(this);
274
+socket_address_inet6::operator == (const socket_address_inet6& rhs) const {
276
+ memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr)) == 0 &&
277
+ m_sockaddr.sin6_port == rhs.m_sockaddr.sin6_port;
281
+socket_address_inet6::operator < (const socket_address_inet6& rhs) const {
282
+ int addr_comp = memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr));
286
+ m_sockaddr.sin6_port < rhs.m_sockaddr.sin6_port);
294
--- a/src/dht/dht_node.cc
295
+++ b/src/dht/dht_node.cc
297
m_recentlyInactive(0),
300
+#ifdef RAK_USE_INET6
301
+ if (sa->family() != rak::socket_address::af_inet &&
302
+ (sa->family() != rak::socket_address::af_inet6 ||
303
+ !sa->sa_inet6()->is_any()))
304
+ throw resource_error("Address not af_inet or in6addr_any");
306
if (sa->family() != rak::socket_address::af_inet)
307
throw resource_error("Address not af_inet");
311
DhtNode::DhtNode(const std::string& id, const Object& cache) :
315
DhtNode::store_cache(Object* container) const {
316
- container->insert_key("i", m_socketAddress.sa_inet()->address_h());
317
- container->insert_key("p", m_socketAddress.sa_inet()->port());
318
+#ifdef RAK_USE_INET6
319
+ if (m_socketAddress.family() == rak::socket_address::af_inet6) {
320
+ // Currently, all we support is in6addr_any (checked in the constructor),
321
+ // which is effectively equivalent to this. Note that we need to specify
322
+ // int64_t explicitly here because a zero constant is special in C++ and
323
+ // thus we need an explicit match.
324
+ container->insert_key("i", int64_t(0));
325
+ container->insert_key("p", m_socketAddress.sa_inet6()->port());
329
+ container->insert_key("i", m_socketAddress.sa_inet()->address_h());
330
+ container->insert_key("p", m_socketAddress.sa_inet()->port());
332
container->insert_key("t", m_lastSeen);
335
--- a/src/dht/dht_server.cc
336
+++ b/src/dht/dht_server.cc
341
+#ifdef RAK_USE_INET6
342
+ // We can currently only process mapped-IPv4 addresses, not real IPv6.
343
+ // Translate them to an af_inet socket_address.
344
+ if (sa.family() == rak::socket_address::af_inet6)
345
+ sa = sa.sa_inet6()->normalize_address();
348
+ if (sa.family() != rak::socket_address::af_inet)
353
// If it's not a valid bencode dictionary at all, it's probably not a DHT
354
--- a/src/torrent/download_info.h
355
+++ b/src/torrent/download_info.h
357
mutable signal_chunk_type m_signalChunkFailed;
360
+#ifdef RAK_USE_INET6
361
+struct SocketAddressCompact6 {
362
+ SocketAddressCompact6() {}
363
+ SocketAddressCompact6(in6_addr a, uint16_t p) : addr(a), port(p) {}
364
+ SocketAddressCompact6(const rak::socket_address_inet6* sa) : addr(sa->address()), port(sa->port_n()) {}
366
+ operator rak::socket_address () const {
367
+ rak::socket_address sa;
368
+ sa.sa_inet6()->clear();
369
+ sa.sa_inet6()->set_port_n(port);
370
+ sa.sa_inet6()->set_address(addr);
378
+ const char* c_str() const { return reinterpret_cast<const char*>(this); }
379
+} __attribute__ ((packed));
385
--- a/src/net/address_list.cc
386
+++ b/src/net/address_list.cc
388
#include <rak/functional.h>
390
#include "address_list.h"
391
+#include "torrent/download_info.h"
399
+#ifdef RAK_USE_INET6
401
+AddressList::parse_address_compact_ipv6(const std::string& s) {
402
+ if (sizeof(const SocketAddressCompact6) != 18)
403
+ throw internal_error("ConnectionList::AddressList::parse_address_compact_ipv6(...) bad struct size.");
405
+ std::copy(reinterpret_cast<const SocketAddressCompact6*>(s.c_str()),
406
+ reinterpret_cast<const SocketAddressCompact6*>(s.c_str() + s.size() - s.size() % sizeof(SocketAddressCompact6)),
407
+ std::back_inserter(*this));
412
--- a/src/net/address_list.h
413
+++ b/src/net/address_list.h
416
void parse_address_compact(raw_string s);
417
void parse_address_compact(const std::string& s);
418
+#ifdef RAK_USE_INET6
419
+ void parse_address_compact_ipv6(const std::string& s);
423
static rak::socket_address parse_address(const Object& b);
425
+++ b/src/net/local_addr.cc
427
+// libTorrent - BitTorrent library
428
+// Copyright (C) 2005-2007, Jari Sundell
430
+// This program is free software; you can redistribute it and/or modify
431
+// it under the terms of the GNU General Public License as published by
432
+// the Free Software Foundation; either version 2 of the License, or
433
+// (at your option) any later version.
435
+// This program is distributed in the hope that it will be useful,
436
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
437
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
438
+// GNU General Public License for more details.
440
+// You should have received a copy of the GNU General Public License
441
+// along with this program; if not, write to the Free Software
442
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
444
+// In addition, as a special exception, the copyright holders give
445
+// permission to link the code of portions of this program with the
446
+// OpenSSL library under certain conditions as described in each
447
+// individual source file, and distribute linked combinations
448
+// including the two.
450
+// You must obey the GNU General Public License in all respects for
451
+// all of the code used other than OpenSSL. If you modify file(s)
452
+// with this exception, you may extend this exception to your version
453
+// of the file(s), but you are not obligated to do so. If you do not
454
+// wish to do so, delete this exception statement from your version.
455
+// If you delete this exception statement from all source files in the
456
+// program, then also delete it here.
458
+// Contact: Jari Sundell <jaris@ifi.uio.no>
461
+// 3185 Skoppum, NORWAY
466
+#include <ifaddrs.h>
467
+#include <rak/socket_address.h>
468
+#include <sys/types.h>
472
+#include <linux/netlink.h>
473
+#include <linux/rtnetlink.h>
476
+#include "torrent/exceptions.h"
477
+#include "socket_fd.h"
478
+#include "local_addr.h"
483
+// IPv4 priority, from highest to lowest:
485
+// 1. Everything else (global address)
486
+// 2. Private address space (10.0.0.0/8, 172.16.0.0/16, 192.168.0.0/24)
487
+// 3. Empty/INADDR_ANY (0.0.0.0)
488
+// 4. Link-local address (169.254.0.0/16)
489
+// 5. Localhost (127.0.0.0/8)
490
+int get_priority_ipv4(const in_addr& addr) {
491
+ if ((addr.s_addr & htonl(0xff000000U)) == htonl(0x7f000000U)) {
494
+ if (addr.s_addr == htonl(0)) {
497
+ if ((addr.s_addr & htonl(0xffff0000U)) == htonl(0xa9fe0000U)) {
500
+ if ((addr.s_addr & htonl(0xff000000U)) == htonl(0x0a000000U) ||
501
+ (addr.s_addr & htonl(0xffff0000U)) == htonl(0xac100000U) ||
502
+ (addr.s_addr & htonl(0xffff0000U)) == htonl(0xc0a80000U)) {
508
+#ifdef RAK_USE_INET6
509
+// IPv6 priority, from highest to lowest:
511
+// 1. Global address (2000::/16 not in 6to4 or Teredo)
512
+// 2. 6to4 (2002::/16)
513
+// 3. Teredo (2001::/32)
514
+// 4. Empty/INADDR_ANY (::)
515
+// 5. Everything else (link-local, ULA, etc.)
516
+int get_priority_ipv6(const in6_addr& addr) {
517
+ const uint32_t *addr32 = reinterpret_cast<const uint32_t *>(addr.s6_addr);
518
+ if (addr32[0] == htonl(0) &&
519
+ addr32[1] == htonl(0) &&
520
+ addr32[2] == htonl(0) &&
521
+ addr32[3] == htonl(0)) {
524
+ if (addr32[0] == htonl(0x20010000)) {
527
+ if ((addr32[0] & htonl(0xffff0000)) == htonl(0x20020000)) {
530
+ if ((addr32[0] & htonl(0xe0000000)) == htonl(0x20000000)) {
537
+int get_priority(const rak::socket_address& addr) {
538
+ switch (addr.family()) {
540
+ return get_priority_ipv4(addr.c_sockaddr_inet()->sin_addr);
541
+#ifdef RAK_USE_INET6
543
+ return get_priority_ipv6(addr.c_sockaddr_inet6()->sin6_addr);
546
+ throw torrent::internal_error("Unknown address family given to compare");
554
+// Linux-specific implementation that understands how to filter away
555
+// understands how to filter away secondary addresses.
556
+bool get_local_address(sa_family_t family, rak::socket_address *address) {
558
+ if (getifaddrs(&ifaddrs)) {
562
+ rak::socket_address best_addr;
565
+ best_addr.sa_inet()->clear();
567
+#ifdef RAK_USE_INET6
569
+ best_addr.sa_inet6()->clear();
573
+ throw torrent::internal_error("Unknown address family given to get_local_address");
576
+ // The bottom bit of the priority is used to hold if the address is
577
+ // a secondary address (e.g. with IPv6 privacy extensions) or not;
578
+ // secondary addresses have lower priority (higher number).
579
+ int best_addr_pri = get_priority(best_addr) * 2;
581
+ // Get all the addresses via Linux' netlink interface.
582
+ int fd = ::socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
587
+ struct sockaddr_nl nladdr;
588
+ memset(&nladdr, 0, sizeof(nladdr));
589
+ nladdr.nl_family = AF_NETLINK;
590
+ if (::bind(fd, (sockaddr *)&nladdr, sizeof(nladdr))) {
595
+ const int seq_no = 1;
600
+ memset(&req, 0, sizeof(req));
602
+ req.nh.nlmsg_len = sizeof(req);
603
+ req.nh.nlmsg_type = RTM_GETADDR;
604
+ req.nh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
605
+ req.nh.nlmsg_pid = getpid();
606
+ req.nh.nlmsg_seq = seq_no;
607
+ req.g.rtgen_family = AF_UNSPEC;
611
+ ret = ::sendto(fd, &req, sizeof(req), 0, (sockaddr *)&nladdr, sizeof(nladdr));
612
+ } while (ret == -1 && errno == EINTR);
622
+ socklen_t len = sizeof(nladdr);
624
+ ret = ::recvfrom(fd, buf, sizeof(buf), 0, (sockaddr *)&nladdr, &len);
625
+ } while (ret == -1 && errno == EINTR);
632
+ for (const nlmsghdr *nlmsg = (const nlmsghdr *)buf;
633
+ NLMSG_OK(nlmsg, ret);
634
+ nlmsg = NLMSG_NEXT(nlmsg, ret)) {
635
+ if (nlmsg->nlmsg_seq != seq_no)
637
+ if (nlmsg->nlmsg_type == NLMSG_DONE) {
641
+ if (nlmsg->nlmsg_type == NLMSG_ERROR) {
645
+ if (nlmsg->nlmsg_type != RTM_NEWADDR)
648
+ const ifaddrmsg *ifa = (const ifaddrmsg *)NLMSG_DATA(nlmsg);
650
+ if (ifa->ifa_family != family)
653
+#ifdef IFA_F_OPTIMISTIC
654
+ if ((ifa->ifa_flags & IFA_F_OPTIMISTIC) != 0)
657
+#ifdef IFA_F_DADFAILED
658
+ if ((ifa->ifa_flags & IFA_F_DADFAILED) != 0)
661
+#ifdef IFA_F_DEPRECATED
662
+ if ((ifa->ifa_flags & IFA_F_DEPRECATED) != 0)
665
+#ifdef IFA_F_TENTATIVE
666
+ if ((ifa->ifa_flags & IFA_F_TENTATIVE) != 0)
670
+ // Since there can be point-to-point links on the machine, we need to keep
671
+ // track of the addresses we've seen for this interface; if we see both
672
+ // IFA_LOCAL and IFA_ADDRESS for an interface, keep only the IFA_LOCAL.
673
+ rak::socket_address this_addr;
674
+ bool seen_addr = false;
675
+ int plen = IFA_PAYLOAD(nlmsg);
676
+ for (const rtattr *rta = IFA_RTA(ifa);
678
+ rta = RTA_NEXT(rta, plen)) {
679
+ if (rta->rta_type != IFA_LOCAL &&
680
+ rta->rta_type != IFA_ADDRESS) {
683
+ if (rta->rta_type == IFA_ADDRESS && seen_addr) {
687
+ switch (ifa->ifa_family) {
689
+ this_addr.sa_inet()->clear();
690
+ this_addr.sa_inet()->set_address(*(const in_addr *)RTA_DATA(rta));
692
+#ifdef RAK_USE_INET6
694
+ this_addr.sa_inet6()->clear();
695
+ this_addr.sa_inet6()->set_address(*(const in6_addr *)RTA_DATA(rta));
703
+ int this_addr_pri = get_priority(this_addr) * 2;
704
+ if ((ifa->ifa_flags & IFA_F_SECONDARY) == IFA_F_SECONDARY) {
708
+ if (this_addr_pri < best_addr_pri) {
709
+ best_addr = this_addr;
710
+ best_addr_pri = this_addr_pri;
716
+ if (!best_addr.is_address_any()) {
717
+ *address = best_addr;
726
+// Generic POSIX variant.
727
+bool get_local_address(sa_family_t family, rak::socket_address *address) {
729
+ if (!sock.open_datagram()) {
733
+ rak::socket_address dummy_dest;
734
+ dummy_dest.clear();
737
+ case rak::socket_address::af_inet:
738
+ dummy_dest.set_address_c_str("4.0.0.0");
740
+#ifdef RAK_USE_INET6
741
+ case rak::socket_address::af_inet6:
742
+ dummy_dest.set_address_c_str("2001:700::");
746
+ throw internal_error("Unknown address family");
748
+ dummy_dest.set_port(80);
750
+ if (!sock.connect(dummy_dest)) {
755
+ bool ret = sock.getsockname(address);
764
+++ b/src/net/local_addr.h
766
+// libTorrent - BitTorrent library
767
+// Copyright (C) 2005-2007, Jari Sundell
769
+// This program is free software; you can redistribute it and/or modify
770
+// it under the terms of the GNU General Public License as published by
771
+// the Free Software Foundation; either version 2 of the License, or
772
+// (at your option) any later version.
774
+// This program is distributed in the hope that it will be useful,
775
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
776
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
777
+// GNU General Public License for more details.
779
+// You should have received a copy of the GNU General Public License
780
+// along with this program; if not, write to the Free Software
781
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
783
+// In addition, as a special exception, the copyright holders give
784
+// permission to link the code of portions of this program with the
785
+// OpenSSL library under certain conditions as described in each
786
+// individual source file, and distribute linked combinations
787
+// including the two.
789
+// You must obey the GNU General Public License in all respects for
790
+// all of the code used other than OpenSSL. If you modify file(s)
791
+// with this exception, you may extend this exception to your version
792
+// of the file(s), but you are not obligated to do so. If you do not
793
+// wish to do so, delete this exception statement from your version.
794
+// If you delete this exception statement from all source files in the
795
+// program, then also delete it here.
797
+// Contact: Jari Sundell <jaris@ifi.uio.no>
800
+// 3185 Skoppum, NORWAY
802
+// A routine to get a local IP address that can be presented to a tracker.
803
+// (Does not use UPnP etc., so will not understand NAT.)
804
+// On a machine with multiple network cards, address selection can be a
805
+// complex process, and in general what's selected is a source/destination
806
+// address pair. However, this routine will give an approximation that will
807
+// be good enough for most purposes and users.
809
+#ifndef LIBTORRENT_NET_LOCAL_ADDR_H
810
+#define LIBTORRENT_NET_LOCAL_ADDR_H
815
+ class socket_address;
820
+// Note: family must currently be rak::af_inet or rak::af_inet6
821
+// (rak::af_unspec won't do); anything else will throw an exception.
822
+// Returns false if no address of the given family could be found,
823
+// either because there are none, or because something went wrong in
824
+// the process (e.g., no free file descriptors).
825
+bool get_local_address(sa_family_t family, rak::socket_address *address);
829
+#endif /* LIBTORRENT_NET_LOCAL_ADDR_H */
830
--- a/src/net/Makefile.am
831
+++ b/src/net/Makefile.am
841
--- a/src/net/Makefile.in
842
+++ b/src/net/Makefile.in
844
CONFIG_CLEAN_VPATH_FILES =
845
LTLIBRARIES = $(noinst_LTLIBRARIES)
846
libsub_net_la_LIBADD =
847
-am_libsub_net_la_OBJECTS = address_list.lo listen.lo socket_base.lo \
848
- socket_datagram.lo socket_fd.lo socket_set.lo socket_stream.lo \
849
- throttle_internal.lo throttle_list.lo
850
+am_libsub_net_la_OBJECTS = address_list.lo local_addr.lo listen.lo \
851
+ socket_base.lo socket_datagram.lo socket_fd.lo socket_set.lo \
852
+ socket_stream.lo throttle_internal.lo throttle_list.lo
853
libsub_net_la_OBJECTS = $(am_libsub_net_la_OBJECTS)
854
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
855
depcomp = $(SHELL) $(top_srcdir)/depcomp
867
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/address_list.Plo@am__quote@
868
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/listen.Plo@am__quote@
869
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/local_addr.Plo@am__quote@
870
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_base.Plo@am__quote@
871
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_datagram.Plo@am__quote@
872
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket_fd.Plo@am__quote@
873
--- a/src/net/socket_datagram.cc
874
+++ b/src/net/socket_datagram.cc
879
- r = ::sendto(m_fileDesc, buffer, length, 0, sa->sa_inet()->c_sockaddr(), sizeof(rak::socket_address_inet));
880
+#ifdef RAK_USE_INET6
881
+ if (m_ipv6_socket && sa->family() == rak::socket_address::pf_inet) {
882
+ rak::socket_address_inet6 sa_mapped = sa->sa_inet()->to_mapped_address();
883
+ r = ::sendto(m_fileDesc, buffer, length, 0, sa_mapped.c_sockaddr(), sizeof(rak::socket_address_inet6));
886
+ r = ::sendto(m_fileDesc, buffer, length, 0, sa->c_sockaddr(), sa->length());
888
r = ::send(m_fileDesc, buffer, length, 0);
890
--- a/src/net/socket_fd.cc
891
+++ b/src/net/socket_fd.cc
896
+#ifdef RAK_USE_INET6
898
+ return setsockopt(m_fd, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) == 0;
901
return setsockopt(m_fd, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) == 0;
904
@@ -112,12 +117,36 @@
907
SocketFd::open_stream() {
908
+#ifdef RAK_USE_INET6
909
+ m_fd = socket(rak::socket_address::pf_inet6, SOCK_STREAM, IPPROTO_TCP);
911
+ m_ipv6_socket = false;
912
+ return (m_fd = socket(rak::socket_address::pf_inet, SOCK_STREAM, IPPROTO_TCP)) != -1;
914
+ m_ipv6_socket = true;
917
+ return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1;
919
return (m_fd = socket(rak::socket_address::pf_inet, SOCK_STREAM, IPPROTO_TCP)) != -1;
924
SocketFd::open_datagram() {
925
+#ifdef RAK_USE_INET6
926
+ m_fd = socket(rak::socket_address::pf_inet6, SOCK_DGRAM, 0);
928
+ m_ipv6_socket = false;
929
+ return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1;
931
+ m_ipv6_socket = true;
934
+ return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1;
936
return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1;
942
SocketFd::bind(const rak::socket_address& sa) {
945
+#ifdef RAK_USE_INET6
946
+ if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) {
947
+ rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address();
948
+ return !::bind(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped));
951
return !::bind(m_fd, sa.c_sockaddr(), sa.length());
955
SocketFd::bind(const rak::socket_address& sa, unsigned int length) {
958
+#ifdef RAK_USE_INET6
959
+ if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) {
960
+ rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address();
961
+ return !::bind(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped));
964
return !::bind(m_fd, sa.c_sockaddr(), length);
967
@@ -149,10 +190,34 @@
968
SocketFd::connect(const rak::socket_address& sa) {
971
+#ifdef RAK_USE_INET6
972
+ if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) {
973
+ rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address();
974
+ return !::connect(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped)) || errno == EINPROGRESS;
977
return !::connect(m_fd, sa.c_sockaddr(), sa.length()) || errno == EINPROGRESS;
981
+SocketFd::getsockname(rak::socket_address *sa) {
984
+ socklen_t len = sizeof(rak::socket_address);
985
+ if (::getsockname(m_fd, sa->c_sockaddr(), &len)) {
989
+#ifdef RAK_USE_INET6
990
+ if (m_ipv6_socket && sa->family() == rak::socket_address::af_inet6) {
991
+ *sa = sa->sa_inet6()->normalize_address();
999
SocketFd::listen(int size) {
1002
@@ -164,7 +229,18 @@
1004
socklen_t len = sizeof(rak::socket_address);
1006
+#ifdef RAK_USE_INET6
1008
+ return SocketFd(::accept(m_fd, NULL, &len));
1010
+ int fd = ::accept(m_fd, sa->c_sockaddr(), &len);
1011
+ if (fd != -1 && m_ipv6_socket && sa->family() == rak::socket_address::af_inet6) {
1012
+ *sa = sa->sa_inet6()->normalize_address();
1014
+ return SocketFd(fd);
1016
return SocketFd(::accept(m_fd, sa != NULL ? sa->c_sockaddr() : NULL, &len));
1021
--- a/src/net/socket_fd.h
1022
+++ b/src/net/socket_fd.h
1024
bool bind(const rak::socket_address& sa);
1025
bool bind(const rak::socket_address& sa, unsigned int length);
1026
bool connect(const rak::socket_address& sa);
1027
+ bool getsockname(rak::socket_address* sa);
1029
bool listen(int size);
1030
SocketFd accept(rak::socket_address* sa);
1032
inline void check_valid() const;
1035
+#ifdef RAK_USE_INET6
1036
+ bool m_ipv6_socket;
1041
--- a/src/torrent/connection_manager.cc
1042
+++ b/src/torrent/connection_manager.cc
1044
m_slotResolver(&resolve_host) {
1046
m_bindAddress = (new rak::socket_address())->c_sockaddr();
1047
- rak::socket_address::cast_from(m_bindAddress)->sa_inet()->clear();
1049
m_localAddress = (new rak::socket_address())->c_sockaddr();
1050
- rak::socket_address::cast_from(m_localAddress)->sa_inet()->clear();
1052
m_proxyAddress = (new rak::socket_address())->c_sockaddr();
1054
+#ifdef RAK_USE_INET6
1055
+ rak::socket_address::cast_from(m_bindAddress)->sa_inet6()->clear();
1056
+ rak::socket_address::cast_from(m_localAddress)->sa_inet6()->clear();
1057
+ rak::socket_address::cast_from(m_proxyAddress)->sa_inet6()->clear();
1059
+ rak::socket_address::cast_from(m_bindAddress)->sa_inet()->clear();
1060
+ rak::socket_address::cast_from(m_localAddress)->sa_inet()->clear();
1061
rak::socket_address::cast_from(m_proxyAddress)->sa_inet()->clear();
1065
ConnectionManager::~ConnectionManager() {
1066
@@ -125,8 +130,10 @@
1067
ConnectionManager::set_bind_address(const sockaddr* sa) {
1068
const rak::socket_address* rsa = rak::socket_address::cast_from(sa);
1070
+#ifndef RAK_USE_INET6
1071
if (rsa->family() != rak::socket_address::af_inet)
1072
throw input_error("Tried to set a bind address that is not an af_inet address.");
1075
rak::socket_address::cast_from(m_bindAddress)->copy(*rsa, rsa->length());
1077
@@ -135,8 +142,10 @@
1078
ConnectionManager::set_local_address(const sockaddr* sa) {
1079
const rak::socket_address* rsa = rak::socket_address::cast_from(sa);
1081
+#ifndef RAK_USE_INET6
1082
if (rsa->family() != rak::socket_address::af_inet)
1083
throw input_error("Tried to set a local address that is not an af_inet address.");
1086
rak::socket_address::cast_from(m_localAddress)->copy(*rsa, rsa->length());
1088
@@ -145,8 +154,10 @@
1089
ConnectionManager::set_proxy_address(const sockaddr* sa) {
1090
const rak::socket_address* rsa = rak::socket_address::cast_from(sa);
1092
+#ifndef RAK_USE_INET6
1093
if (rsa->family() != rak::socket_address::af_inet)
1094
throw input_error("Tried to set a proxy address that is not an af_inet address.");
1097
rak::socket_address::cast_from(m_proxyAddress)->copy(*rsa, rsa->length());
1099
--- a/src/torrent/event.h
1100
+++ b/src/torrent/event.h
1106
+#ifdef RAK_USE_INET6
1107
+ bool m_ipv6_socket;
1112
--- a/src/torrent/peer/peer_list.cc
1113
+++ b/src/torrent/peer/peer_list.cc
1116
return sa1->sa_inet()->address_h() < sa2->sa_inet()->address_h();
1118
+#ifdef RAK_USE_INET6
1120
+ const in6_addr addr1 = sa1->sa_inet6()->address();
1121
+ const in6_addr addr2 = sa2->sa_inet6()->address();
1122
+ return memcmp(&addr1, &addr2, sizeof(in6_addr)) < 0;
1126
- // When we implement INET6 handling, embed the ipv4 address in
1127
- // the ipv6 address.
1128
throw internal_error("socket_address_key(...) tried to compare an invalid family type.");
1134
socket_address_key::is_comparable(const sockaddr* sa) {
1135
- return rak::socket_address::cast_from(sa)->family() == rak::socket_address::af_inet;
1136
+ return rak::socket_address::cast_from(sa)->family() == rak::socket_address::af_inet ||
1137
+ rak::socket_address::cast_from(sa)->family() == rak::socket_address::af_inet6;
1140
struct peer_list_equal_port : public std::binary_function<PeerList::reference, uint16_t, bool> {
1141
--- a/src/tracker/tracker_http.cc
1142
+++ b/src/tracker/tracker_http.cc
1144
#include <rak/string_manip.h>
1146
#include "net/address_list.h"
1147
+#include "net/local_addr.h"
1148
#include "torrent/connection_manager.h"
1149
#include "torrent/download_info.h"
1150
#include "torrent/exceptions.h"
1151
@@ -114,9 +115,16 @@
1153
const rak::socket_address* localAddress = rak::socket_address::cast_from(manager->connection_manager()->local_address());
1155
- if (localAddress->family() == rak::socket_address::af_inet &&
1156
- !localAddress->sa_inet()->is_address_any())
1157
+ if (!localAddress->is_address_any())
1158
s << "&ip=" << localAddress->address_str();
1160
+#ifdef RAK_USE_INET6
1161
+ if (localAddress->is_address_any() || localAddress->family() != rak::socket_address::pf_inet6) {
1162
+ rak::socket_address local_v6;
1163
+ if (get_local_address(rak::socket_address::af_inet6, &local_v6))
1164
+ s << "&ipv6=" << rak::copy_escape_html(local_v6.address_str());
1168
if (info->is_compact())
1170
@@ -220,18 +228,34 @@
1175
- // Due to some trackers sending the wrong type when no peers are
1176
- // available, don't bork on it.
1177
- if (b.get_key("peers").is_string())
1178
- l.parse_address_compact(b.get_key_string("peers"));
1179
+ if (!b.has_key("peers")
1180
+#ifdef RAK_USE_INET6
1181
+ && !b.has_key("peers6")
1184
+ return receive_failed("No peers returned");
1187
- else if (b.get_key("peers").is_list())
1188
- l.parse_address_normal(b.get_key_list("peers"));
1189
+ if (b.has_key("peers")) {
1191
+ // Due to some trackers sending the wrong type when no peers are
1192
+ // available, don't bork on it.
1193
+ if (b.get_key("peers").is_string())
1194
+ l.parse_address_compact(b.get_key_string("peers"));
1196
+ else if (b.get_key("peers").is_list())
1197
+ l.parse_address_normal(b.get_key_list("peers"));
1199
+ } catch (bencode_error& e) {
1200
+ return receive_failed(e.what());
1204
- } catch (bencode_error& e) {
1205
- return receive_failed(e.what());
1206
+#ifdef RAK_USE_INET6
1207
+ if (b.has_key("peers6")) {
1208
+ l.parse_address_compact_ipv6(b.get_key_string("peers6"));
1213
m_parent->receive_success(this, &l);
1214
--- a/src/tracker/tracker_udp.cc
1215
+++ b/src/tracker/tracker_udp.cc
1216
@@ -273,11 +273,18 @@
1218
const rak::socket_address* localAddress = rak::socket_address::cast_from(manager->connection_manager()->local_address());
1220
- // This code assumes we're have a inet address.
1221
+#ifdef RAK_USE_INET6
1222
+ uint32_t local_addr = 0;
1223
+ if (localAddress->family() == rak::socket_address::af_inet)
1224
+ local_addr = localAddress->sa_inet()->address_n();
1226
if (localAddress->family() != rak::socket_address::af_inet)
1227
throw internal_error("TrackerUdp::prepare_announce_input() info->local_address() not of family AF_INET.");
1229
+ uint32_t local_addr = localAddress->sa_inet()->address_n();
1232
- m_writeBuffer->write_32_n(localAddress->sa_inet()->address_n());
1233
+ m_writeBuffer->write_32_n(local_addr);
1234
m_writeBuffer->write_32(m_parent->key());
1235
m_writeBuffer->write_32(m_parent->numwant());
1236
m_writeBuffer->write_16(manager->connection_manager()->listen_port());