diff -ur rtorrent-0.8.6.orig/rak/socket_address.h rtorrent-0.8.6/rak/socket_address.h
--- rtorrent-0.8.6.orig/rak/socket_address.h	2009-11-12 09:03:48.000000000 +0100
+++ rtorrent-0.8.6/rak/socket_address.h	2010-07-23 14:45:07.000000000 +0200
@@ -145,7 +145,7 @@
   };
 };
 
-// Remeber to set the AF_INET.
+// Remember to set the AF_INET.
 
 class socket_address_inet {
 public:
@@ -184,6 +184,10 @@
 
   const sockaddr*     c_sockaddr() const                      { return reinterpret_cast<const sockaddr*>(&m_sockaddr); }
   const sockaddr_in*  c_sockaddr_inet() const                 { return &m_sockaddr; }
+  
+#ifdef RAK_USE_INET6
+  socket_address_inet6 to_mapped_address() const;
+#endif
 
   bool                operator == (const socket_address_inet& rhs) const;
   bool                operator < (const socket_address_inet& rhs) const;
@@ -192,6 +196,52 @@
   struct sockaddr_in  m_sockaddr;
 };
 
+#ifdef RAK_USE_INET6
+// Remember to set the AF_INET6.
+
+class socket_address_inet6 {
+public:
+  bool                is_any() const                          { return is_port_any() && is_address_any(); }
+  bool                is_valid() const                        { return !is_port_any() && !is_address_any(); }
+  bool                is_port_any() const                     { return port() == 0; }
+  bool                is_address_any() const                  { return std::memcmp(&m_sockaddr.sin6_addr, &in6addr_any, sizeof(in6_addr)) == 0; }
+
+  void                clear()                                 { std::memset(this, 0, sizeof(socket_address_inet6)); set_family(); }
+
+  uint16_t            port() const                            { return ntohs(m_sockaddr.sin6_port); }
+  uint16_t            port_n() const                          { return m_sockaddr.sin6_port; }
+  void                set_port(uint16_t p)                    { m_sockaddr.sin6_port = htons(p); }
+  void                set_port_n(uint16_t p)                  { m_sockaddr.sin6_port = p; }
+
+  in6_addr            address() const                         { return m_sockaddr.sin6_addr; }
+  std::string         address_str() const;
+  bool                address_c_str(char* buf, socklen_t size) const;
+
+  void                set_address(in6_addr a)                 { m_sockaddr.sin6_addr = a; }
+  bool                set_address_str(const std::string& a)   { return set_address_c_str(a.c_str()); }
+  bool                set_address_c_str(const char* a);
+
+  void                set_address_any()                       { set_port(0); set_address(in6addr_any); }
+
+  sa_family_t         family() const                          { return m_sockaddr.sin6_family; }
+  void                set_family()                            { m_sockaddr.sin6_family = AF_INET6; }
+
+  sockaddr*           c_sockaddr()                            { return reinterpret_cast<sockaddr*>(&m_sockaddr); }
+  sockaddr_in6*       c_sockaddr_inet6()                      { return &m_sockaddr; }
+
+  const sockaddr*     c_sockaddr() const                      { return reinterpret_cast<const sockaddr*>(&m_sockaddr); }
+  const sockaddr_in6* c_sockaddr_inet6() const                { return &m_sockaddr; }
+
+  socket_address      normalize_address() const;
+
+  bool                operator == (const socket_address_inet6& rhs) const;
+  bool                operator < (const socket_address_inet6& rhs) const;
+
+private:
+  struct sockaddr_in6 m_sockaddr;
+};
+#endif
+
 // Unique key for the address, excluding port numbers etc.
 class socket_address_key {
 public:
@@ -241,8 +291,10 @@
   switch (family()) {
   case af_inet:
     return sa_inet()->is_valid();
-//   case af_inet6:
-//     return sa_inet6().is_valid();
+#ifdef RAK_USE_INET6
+  case af_inet6:
+    return sa_inet6()->is_valid();
+#endif
   default:
     return false;
   }
@@ -253,6 +305,10 @@
   switch (family()) {
   case af_inet:
     return !sa_inet()->is_address_any();
+#ifdef RAK_USE_INET6
+  case af_inet6:
+    return !sa_inet6()->is_address_any();
+#endif
   default:
     return false;
   }
@@ -263,6 +319,10 @@
   switch (family()) {
   case af_inet:
     return sa_inet()->is_address_any();
+#ifdef RAK_USE_INET6
+  case af_inet6:
+    return sa_inet6()->is_address_any();
+#endif
   default:
     return true;
   }
@@ -273,6 +333,10 @@
   switch (family()) {
   case af_inet:
     return sa_inet()->port();
+#ifdef RAK_USE_INET6
+  case af_inet6:
+    return sa_inet6()->port();
+#endif
   default:
     return 0;
   }
@@ -283,6 +347,10 @@
   switch (family()) {
   case af_inet:
     return sa_inet()->set_port(p);
+#ifdef RAK_USE_INET6
+  case af_inet6:
+    return sa_inet6()->set_port(p);
+#endif
   default:
     break;
   }
@@ -293,6 +361,10 @@
   switch (family()) {
   case af_inet:
     return sa_inet()->address_str();
+#ifdef RAK_USE_INET6
+  case af_inet6:
+    return sa_inet6()->address_str();
+#endif
   default:
     return std::string();
   }
@@ -303,6 +375,10 @@
   switch (family()) {
   case af_inet:
     return sa_inet()->address_c_str(buf, size);
+#ifdef RAK_USE_INET6
+  case af_inet6:
+    return sa_inet6()->address_c_str(buf, size);
+#endif
   default:
     return false;
   }
@@ -314,6 +390,12 @@
     sa_inet()->set_family();
     return true;
 
+#ifdef RAK_USE_INET6
+  } else if (sa_inet6()->set_address_c_str(a)) {
+    sa_inet6()->set_family();
+    return true;
+#endif
+
   } else {
     return false;
   }
@@ -325,6 +407,10 @@
   switch(family()) {
   case af_inet:
     return sizeof(sockaddr_in);
+#ifdef RAK_USE_INET6
+  case af_inet6:
+    return sizeof(sockaddr_in6);
+#endif
   default:
     return 0;
   }      
@@ -349,8 +435,10 @@
   switch (family()) {
   case af_inet:
     return *sa_inet() == *rhs.sa_inet();
-//   case af_inet6:
-//     return *sa_inet6() == *rhs.sa_inet6();
+#ifdef RAK_USE_INET6
+  case af_inet6:
+    return *sa_inet6() == *rhs.sa_inet6();
+#endif
   default:
     throw std::logic_error("socket_address::operator == (rhs) invalid type comparison.");
   }
@@ -364,8 +452,10 @@
   switch (family()) {
   case af_inet:
     return *sa_inet() < *rhs.sa_inet();
-//   case af_inet6:
-//     return *sa_inet6() < *rhs.sa_inet6();
+#ifdef RAK_USE_INET6
+  case af_inet6:
+    return *sa_inet6() < *rhs.sa_inet6();
+#endif
   default:
     throw std::logic_error("socket_address::operator < (rhs) invalid type comparison.");
   }
@@ -391,6 +481,23 @@
   return inet_pton(AF_INET, a, &m_sockaddr.sin_addr);
 }
 
+#ifdef RAK_USE_INET6
+inline socket_address_inet6
+socket_address_inet::to_mapped_address() const {
+  uint32_t addr32[4];
+  addr32[0] = 0;
+  addr32[1] = 0;
+  addr32[2] = htonl(0xffff);
+  addr32[3] = m_sockaddr.sin_addr.s_addr;
+  
+  socket_address_inet6 sa;
+  sa.clear();
+  sa.set_address(*reinterpret_cast<in6_addr *>(addr32));
+  sa.set_port_n(m_sockaddr.sin_port);
+  return sa;
+}
+#endif
+
 inline bool
 socket_address_inet::operator == (const socket_address_inet& rhs) const {
   return
@@ -406,6 +513,59 @@
      m_sockaddr.sin_port < rhs.m_sockaddr.sin_port);
 }
 
+#ifdef RAK_USE_INET6
+
+inline std::string
+socket_address_inet6::address_str() const {
+  char buf[INET6_ADDRSTRLEN];
+
+  if (!address_c_str(buf, INET6_ADDRSTRLEN))
+    return std::string();
+
+  return std::string(buf);
+}
+
+inline bool
+socket_address_inet6::address_c_str(char* buf, socklen_t size) const {
+  return inet_ntop(family(), &m_sockaddr.sin6_addr, buf, size);
+}
+
+inline bool
+socket_address_inet6::set_address_c_str(const char* a) {
+  return inet_pton(AF_INET6, a, &m_sockaddr.sin6_addr);
+}
+
+inline socket_address
+socket_address_inet6::normalize_address() const {
+  const uint32_t *addr32 = reinterpret_cast<const uint32_t *>(m_sockaddr.sin6_addr.s6_addr);
+  if (addr32[0] == 0 && addr32[1] == 0 && addr32[2] == htonl(0xffff)) {
+    socket_address addr4;
+    addr4.sa_inet()->set_family();
+    addr4.sa_inet()->set_address_n(addr32[3]);
+    addr4.sa_inet()->set_port_n(m_sockaddr.sin6_port);
+    return addr4;
+  }
+  return *reinterpret_cast<const socket_address*>(this);
+}
+
+inline bool
+socket_address_inet6::operator == (const socket_address_inet6& rhs) const {
+  return
+    memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr)) == 0 &&
+    m_sockaddr.sin6_port == rhs.m_sockaddr.sin6_port;
+}
+
+inline bool
+socket_address_inet6::operator < (const socket_address_inet6& rhs) const {
+  int addr_comp = memcmp(&m_sockaddr.sin6_addr, &rhs.m_sockaddr.sin6_addr, sizeof(in6_addr));
+  return
+    addr_comp < 0 ||
+    (addr_comp == 0 ||
+     m_sockaddr.sin6_port < rhs.m_sockaddr.sin6_port);
+}
+
+#endif
+
 }
 
 #endif
diff -ur rtorrent-0.8.6.orig/src/command_peer.cc rtorrent-0.8.6/src/command_peer.cc
--- rtorrent-0.8.6.orig/src/command_peer.cc	2009-11-12 09:03:48.000000000 +0100
+++ rtorrent-0.8.6/src/command_peer.cc	2010-07-23 14:45:07.000000000 +0200
@@ -68,7 +68,13 @@
 
 torrent::Object
 retrieve_p_address(torrent::Peer* peer) {
-  return rak::socket_address::cast_from(peer->peer_info()->socket_address())->address_str();
+  const rak::socket_address *addr = rak::socket_address::cast_from(peer->peer_info()->socket_address());
+#ifdef RAK_USE_INET6
+  if (addr->family() == rak::socket_address::af_inet6)
+    return "[" + addr->address_str() + "]";
+  else
+#endif
+  return addr->address_str();
 }
 
 torrent::Object
diff -ur rtorrent-0.8.6.orig/src/core/curl_get.cc rtorrent-0.8.6/src/core/curl_get.cc
--- rtorrent-0.8.6.orig/src/core/curl_get.cc	2009-11-12 09:03:44.000000000 +0100
+++ rtorrent-0.8.6/src/core/curl_get.cc	2010-07-23 14:45:07.000000000 +0200
@@ -88,8 +88,20 @@
   curl_easy_setopt(m_handle, CURLOPT_NOSIGNAL,       (long)1);
   curl_easy_setopt(m_handle, CURLOPT_FOLLOWLOCATION, (long)1);
   curl_easy_setopt(m_handle, CURLOPT_MAXREDIRS,      (long)5);
+
+  // Even when IPv6-enabled, we don't want to use CURL_IPRESOLVE_WHATEVER,
+  // since that will usually prefer connecting over IPv6 to the tracker.
+  // Since it's usually a lot easier to find our global IPv6 address
+  // (if we have one) than our global IPv4 address, we prefer connecting
+  // over IPv4 if we can, so that the tracker will get our IPv4 address
+  // that way. If the resolve fails, CurlStack will call retry_ipv6()
+  // on us and we'll make a second attempt with CURL_IPRESOLVE_V6.
   curl_easy_setopt(m_handle, CURLOPT_IPRESOLVE,      CURL_IPRESOLVE_V4);
+
   curl_easy_setopt(m_handle, CURLOPT_ENCODING,       "");
+#ifdef RAK_USE_INET6
+  m_ipv6 = false;
+#endif
 
   m_stack->add_get(this);
 }
@@ -107,6 +119,17 @@
   m_handle = NULL;
 }
 
+#ifdef RAK_USE_INET6
+void
+CurlGet::retry_ipv6() {
+  CURL* nhandle = curl_easy_duphandle(m_handle);
+  curl_easy_setopt(nhandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
+  curl_easy_cleanup(m_handle);
+  m_handle = nhandle;
+  m_ipv6 = true;
+}
+#endif
+
 void
 CurlGet::receive_timeout() {
   return m_stack->transfer_done(m_handle, "Timed out");
diff -ur rtorrent-0.8.6.orig/src/core/curl_get.h rtorrent-0.8.6/src/core/curl_get.h
--- rtorrent-0.8.6.orig/src/core/curl_get.h	2009-11-12 09:03:44.000000000 +0100
+++ rtorrent-0.8.6/src/core/curl_get.h	2010-07-23 14:45:07.000000000 +0200
@@ -56,6 +56,10 @@
 
   void               start();
   void               close();
+#ifdef RAK_USE_INET6
+  bool               is_using_ipv6()    { return m_ipv6; }
+  void               retry_ipv6();
+#endif
 
   bool               is_busy() const    { return m_handle; }
   bool               is_active() const  { return m_active; }
@@ -74,6 +78,9 @@
   void               receive_timeout();
 
   bool               m_active;
+#ifdef RAK_USE_INET6
+  bool               m_ipv6;
+#endif
 
   rak::priority_item m_taskTimeout;
   
diff -ur rtorrent-0.8.6.orig/src/core/curl_stack.cc rtorrent-0.8.6/src/core/curl_stack.cc
--- rtorrent-0.8.6.orig/src/core/curl_stack.cc	2009-11-12 09:03:44.000000000 +0100
+++ rtorrent-0.8.6/src/core/curl_stack.cc	2010-07-23 14:45:07.000000000 +0200
@@ -111,6 +111,21 @@
         if (msg->msg != CURLMSG_DONE)
           throw torrent::internal_error("CurlStack::receive_action() msg->msg != CURLMSG_DONE.");
 
+#ifdef RAK_USE_INET6
+        if (msg->data.result == CURLE_COULDNT_RESOLVE_HOST) {
+          iterator itr = std::find_if(begin(), end(), rak::equal(msg->easy_handle, std::mem_fun(&CurlGet::handle)));
+
+          if (itr == end())
+            throw torrent::internal_error("Could not find CurlGet when calling CurlStack::receive_action.");
+
+          if (!(*itr)->is_using_ipv6()) {
+            (*itr)->retry_ipv6();
+            if (curl_multi_add_handle((CURLM*)m_handle, (*itr)->handle()) > 0)
+              throw torrent::internal_error("Error calling curl_multi_add_handle.");
+            continue;
+          }
+        } else
+#endif
 	transfer_done(msg->easy_handle, msg->data.result == CURLE_OK ? NULL : curl_easy_strerror(msg->data.result));
       }
 
diff -ur rtorrent-0.8.6.orig/src/display/window_peer_list.cc rtorrent-0.8.6/src/display/window_peer_list.cc
--- rtorrent-0.8.6.orig/src/display/window_peer_list.cc	2009-11-12 09:03:47.000000000 +0100
+++ rtorrent-0.8.6/src/display/window_peer_list.cc	2010-07-23 14:45:07.000000000 +0200
@@ -68,7 +68,11 @@
   int x = 2;
   int y = 0;
 
-  m_canvas->print(x, y, "IP");     x += 16;
+#ifdef RAK_USE_INET6
+  m_canvas->print(x, y, "IP");      x += 25;
+#else
+  m_canvas->print(x, y, "IP");      x += 16;
+#endif
   m_canvas->print(x, y, "UP");      x += 7;
   m_canvas->print(x, y, "DOWN");    x += 7;
   m_canvas->print(x, y, "PEER");    x += 7;
@@ -99,10 +103,21 @@
 
     x = 0;
 
+    std::string ip_address = rak::socket_address::cast_from(p->address())->address_str();
+#ifdef RAK_USE_INET6
+    if (ip_address.size() >= 24) {
+      ip_address.replace(ip_address.begin() + 21, ip_address.end(), "...");
+    }
+#endif
+
     m_canvas->print(x, y, "%c %s",
                     range.first == *m_focus ? '*' : ' ',
-                    rak::socket_address::cast_from(p->address())->address_str().c_str());
+                    ip_address.c_str());
+#ifdef RAK_USE_INET6
+    x += 27;
+#else
     x += 18;
+#endif
 
     m_canvas->print(x, y, "%.1f", (double)p->up_rate()->rate() / 1024); x += 7;
     m_canvas->print(x, y, "%.1f", (double)p->down_rate()->rate() / 1024); x += 7;
diff -ur rtorrent-0.8.6.orig/src/utils/socket_fd.cc rtorrent-0.8.6/src/utils/socket_fd.cc
--- rtorrent-0.8.6.orig/src/utils/socket_fd.cc	2009-11-12 09:03:46.000000000 +0100
+++ rtorrent-0.8.6/src/utils/socket_fd.cc	2010-07-23 23:11:07.000000000 +0200
@@ -71,6 +71,11 @@
   check_valid();
   int opt = p;
 
+#ifdef RAK_USE_INET6
+  if (m_ipv6_socket)
+    return setsockopt(m_fd, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) == 0;
+  else
+#endif
   return setsockopt(m_fd, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) == 0;
 }
 
@@ -130,12 +135,36 @@
 
 bool
 SocketFd::open_stream() {
+#ifdef RAK_USE_INET6
+  m_fd = socket(rak::socket_address::pf_inet6, SOCK_STREAM, IPPROTO_TCP);
+  if (m_fd == -1) {
+    m_ipv6_socket = false;
+    return (m_fd = socket(rak::socket_address::pf_inet, SOCK_STREAM, IPPROTO_TCP)) != -1;
+  }
+  m_ipv6_socket = true;
+
+  int zero = 0;
+  return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1;
+#else
   return (m_fd = socket(rak::socket_address::pf_inet, SOCK_STREAM, IPPROTO_TCP)) != -1;
+#endif
 }
 
 bool
 SocketFd::open_datagram() {
+#ifdef RAK_USE_INET6
+  m_fd = socket(rak::socket_address::pf_inet6, SOCK_DGRAM, 0);
+  if (m_fd == -1) {
+    m_ipv6_socket = false;
+    return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1;
+  }
+  m_ipv6_socket = true;
+
+  int zero = 0;
+  return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1;
+#else
   return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1;
+#endif
 }
 
 bool
@@ -153,6 +182,12 @@
 SocketFd::bind(const rak::socket_address& sa) {
   check_valid();
 
+#ifdef RAK_USE_INET6
+  if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) {
+    rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address();
+    return !::bind(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped));
+  }
+#endif
   return !::bind(m_fd, sa.c_sockaddr(), sa.length());
 }
 
@@ -160,6 +195,12 @@
 SocketFd::bind(const rak::socket_address& sa, unsigned int length) {
   check_valid();
 
+#ifdef RAK_USE_INET6
+  if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) {
+    rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address();
+    return !::bind(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped));
+  }
+#endif
   return !::bind(m_fd, sa.c_sockaddr(), length);
 }
 
@@ -167,10 +208,34 @@
 SocketFd::connect(const rak::socket_address& sa) {
   check_valid();
 
+#ifdef RAK_USE_INET6
+  if (m_ipv6_socket && sa.family() == rak::socket_address::pf_inet) {
+    rak::socket_address_inet6 sa_mapped = sa.sa_inet()->to_mapped_address();
+    return !::connect(m_fd, sa_mapped.c_sockaddr(), sizeof(sa_mapped)) || errno == EINPROGRESS;
+  }
+#endif
   return !::connect(m_fd, sa.c_sockaddr(), sa.length()) || errno == EINPROGRESS;
 }
 
 bool
+SocketFd::getsockname(rak::socket_address *sa) {
+  check_valid();
+
+  socklen_t len = sizeof(rak::socket_address);
+  if (::getsockname(m_fd, sa->c_sockaddr(), &len)) {
+    return false;
+  }
+
+#ifdef RAK_USE_INET6
+  if (m_ipv6_socket && sa->family() == rak::socket_address::af_inet6) {
+    *sa = sa->sa_inet6()->normalize_address();
+  }
+#endif
+
+  return true;
+}
+
+bool
 SocketFd::listen(int size) {
   check_valid();
 
@@ -182,7 +247,18 @@
   check_valid();
   socklen_t len = sizeof(rak::socket_address);
 
+#ifdef RAK_USE_INET6
+  if (sa == NULL) {
+    return SocketFd(::accept(m_fd, NULL, &len));
+  }
+  int fd = ::accept(m_fd, sa->c_sockaddr(), &len);
+  if (fd != -1 && m_ipv6_socket && sa->family() == rak::socket_address::af_inet6) {
+    *sa = sa->sa_inet6()->normalize_address();
+  }
+  return SocketFd(fd);
+#else
   return SocketFd(::accept(m_fd, sa != NULL ? sa->c_sockaddr() : NULL, &len));
+#endif
 }
 
 // unsigned int
diff -ur rtorrent-0.8.6.orig/src/utils/socket_fd.h rtorrent-0.8.6/src/utils/socket_fd.h
--- rtorrent-0.8.6.orig/src/utils/socket_fd.h	2009-11-12 09:03:46.000000000 +0100
+++ rtorrent-0.8.6/src/utils/socket_fd.h	2010-07-23 14:45:07.000000000 +0200
@@ -80,6 +80,7 @@
   bool                bind(const rak::socket_address& sa);
   bool                bind(const rak::socket_address& sa, unsigned int length);
   bool                connect(const rak::socket_address& sa);
+  bool                getsockname(rak::socket_address* sa);
 
   bool                listen(int size);
   SocketFd            accept(rak::socket_address* sa);
@@ -91,6 +92,9 @@
   inline void         check_valid() const;
 
   int                 m_fd;
+#ifdef RAK_USE_INET6
+  bool                m_ipv6_socket;
+#endif
 };
 
 }
