rakshasa / rtorrent

rTorrent BitTorrent client
https://github.com/rakshasa/rtorrent/wiki
GNU General Public License v2.0
4.07k stars 408 forks source link

IPv6 OpenBSD #820

Open namtsui opened 5 years ago

namtsui commented 5 years ago

I am trying to compile rtorrent 0.9.7 / libtorrent 0.13.7 on OpenBSD. It is similar to https://github.com/rakshasa/rtorrent/issues/732 but with a different cause.

rtorrent closes on startup with

rtorrent: Could not allocate socket for listening.

in net/socket_fd.cc SocketFd::open_stream() (https://github.com/rakshasa/libtorrent/blob/ef1e7c0d2d479c141b83b2949e99cb5dc9255ea6/src/net/socket_fd.cc#L138): if (!set_ipv6_v6only(false)) {

in set_ipv6_v6_only (https://github.com/rakshasa/libtorrent/blob/ef1e7c0d2d479c141b83b2949e99cb5dc9255ea6/src/net/socket_fd.cc#L95): setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY...

libtorrent is trying to set the IPV6_V6ONLY flag to false to indicate: from ipv6(7) on Linux

If this flag is set to false (zero), then the socket can be used to send and receive packets to and from an IPv6 address or an IPv4-mapped IPv6 address.

However, on OpenBSD, IPv6 sockets are read-only and cannot support IPv4. from ip6(4) on OpenBSD

 IPV6_V6ONLY int *
         Get or set whether only IPv6 connections can be made to this
         socket.  For wildcard sockets, this can restrict connections to
         IPv6 only.  With OpenBSD IPv6 sockets are always IPv6-only, so
         the socket option is read-only (not modifiable)

I was able to fix it by forcing IPv4 in open_stream(), as follows. With this patch and adding bind = 0.0.0.0 to ~/.rtorrent.rc (as suggested in the other thread), rtorrent works OK.

I do have IPv6 disabled on OpenBSD, and perhaps I could try setting up IPv6 as a potential solution. I would like to use IPv4 without patching the code too heavily.

The root cause is the difference in behavior of IPV6_V6ONLY between Linux and OpenBSD. What do you think?

Disable IPv6 and force IPv4.
(https://github.com/rakshasa/rtorrent/issues/732)
Works around this error message on startup: "rtorrent: Could not allocate
socket for listening." The suggested bind=0.0.0.0 fix does not work.

Index: src/net/socket_fd.cc
--- src/net/socket_fd.cc.orig
+++ src/net/socket_fd.cc
@@ -126,21 +126,8 @@

 bool
 SocketFd::open_stream() {
-  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;
-
-  if (!set_ipv6_v6only(false)) {
-    close();
-    return false;
-  }
-
-  return true;
+  m_ipv6_socket = false;
+  return (m_fd = socket(rak::socket_address::pf_inet, SOCK_STREAM, IPPROTO_TCP)) != -1;
 }

 bool
namtsui commented 5 years ago

rtorrent would crash with this error so I stubbed out more IPv6 code in open_datagram(). The stability seems to have improved with no more crashes. While it is not ideal that I am bypassing IPv6 altogether, this is just a small update.

Caught internal_error: SocketFd::close() called on an invalid file descriptor Stack dump not enabled.

Disable IPv6 and force IPv4.
(https://github.com/rakshasa/rtorrent/issues/732)
Works around this error message on startup: "rtorrent: Could not allocate
socket for listening." The suggested bind=0.0.0.0 fix does not work.

Index: src/net/socket_fd.cc
--- src/net/socket_fd.cc.orig
+++ src/net/socket_fd.cc
@@ -126,40 +126,14 @@

 bool
 SocketFd::open_stream() {
-  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;
-
-  if (!set_ipv6_v6only(false)) {
-    close();
-    return false;
-  }
-
-  return true;
+  m_ipv6_socket = false;
+  return (m_fd = socket(rak::socket_address::pf_inet, SOCK_STREAM, IPPROTO_TCP)) != -1;
 }

 bool
 SocketFd::open_datagram() {
-  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;
-
-  if (!set_ipv6_v6only(false)) {
-    close();
-    return false;
-  }
-
-  return true;
+  m_ipv6_socket = false;
+  return (m_fd = socket(rak::socket_address::pf_inet, SOCK_DGRAM, 0)) != -1;
 }

 bool
moralground commented 2 years ago

Any update on this? Seems to be blocking an update to the latest version on OpenBSD.

rakshasa commented 2 years ago

Not at the moment, the next step when I'm ready to work on rtorrent will be to finish the ipv4/6 CI and fix issues on linux.