Ticket #1111 (new enhancement)

Opened 6 years ago

Last modified 22 months ago

Support for IPv6?

Reported by: Elvis Bosch Owned by: rakshasa
Priority: high Component: rtorrent
Version: Severity: minor
Keywords: IPv6 Cc:

Description

When can we expect support for IPv6?

The most simple support (working IPv6 only) should be trivial to implement. The only real problem should occur when working with trackers/swarms, that use IPv4 and IPv6 at the same time. For this case I found some interessting suggestions at:

 http://tinyurl.com/3dorca  http://tinyurl.com/3bajew

Attachments

rtorrent-0.8.7-ipv6-08.patch Download (21.4 KB) - added by anonymous 2 years ago.
libtorrent-0.12.7-ipv6-08.patch Download (40.3 KB) - added by anonymous 2 years ago.

Change History

comment:1 follow-up: ↓ 2 Changed 5 years ago by anonymous

any updates on this?

comment:2 in reply to: ↑ 1 Changed 5 years ago by anonymous

Replying to anonymous:

any updates on this?

Doesn't look so. In the meantime other clients get ahaed in terms of IPv6 support.

BTW, additional to the suggestions in the first post here, there seems to be some official extension, available at  http://www.bittorrent.org/ipv6_tracker_extension.html Thoug I think the one above seems to be the cleaner solution.

comment:3 Changed 5 years ago by anonymous

I really need IPv6 right now. I'm using a private tracker where IPv6 is the standard. Is there a patch or any kind of support for it?

comment:4 Changed 4 years ago by Fefe

Piratebay as of today has an IPv6 tracker. Now would be the perfect time to get IPv6 support.

comment:5 Changed 4 years ago by anonymous

Supporting IPv6 purely for the transport of tracker announces and .torrent file download would be next to trivial (change CURLOPT_IPRESOLVE to CURL_IPRESOLVE_WHATEVER in curl_get.cc). Supporting ipv6 peer connections would be considerably more effort on the other hand.

Note that CURL_IPRESOLVE_WHATEVER may not work if libcurl is built with c-ares, as c-ares can currently return only ipv4 or ipv6 addresses. So if you set it to CURL_IPRESOLVE_V6 it may break ipv4 trackers if libcurl is built with c-ares. I'm not sure if recent libcurl versions fix this.

comment:6 Changed 4 years ago by anonymous

The Pirate Bay now adds support for IPv6 to their system:

 http://thepiratebay.org/blog/146

This might increase the incentive to implement IPv6 support in libTorrent/rTorrent.

comment:7 Changed 4 years ago by rakshasa

Don't have time to set up and test this.

comment:8 Changed 4 years ago by anonymous

For those who don't have a time to setup IPv6 on unix systems, install miredo ( http://www.simphalempin.com/dev/miredo/), run miredo with default config and that's all. You will get ipv6 thanks to teredo protocol.

comment:9 Changed 4 years ago by anonymous

Not sure if it is appropriate to add this here, but ever since TPB started supporting IPv6 I've been unable to use any of their torrents, no errors, just no peers to connect to. Changing the tracker address to the IPv4 address of tracker.thepiratebay.org makes it all work again. Not sure if this is simply the way this is supposed to work like this (since it does make sense to me that if you connect to a tracker over IPv6 you only get IPv6 peers, of which there probably aren't too many.), but might be worth mentioning for other people experiencing the same problem.

Additionally maybe it would be nice if there was a way to force IPv6 to be disabled for the transitional period.

comment:10 Changed 4 years ago by anonymous

rtorrent explicitly tells libcurl to disable ipv6 for tracker announces though

comment:11 Changed 4 years ago by nanonyme

Hmm, if it's true that you only get IPv4 addresses when connecting to the tracker over IPv4, would just mean the client needs to poll the tracker double the amount of times (half on IPv4, half on IPv6) if the client has both native IPv4 and native IPv6. Bittorrent over a tunnel is pretty much moronic. rakshasa, while I understand doing a dual-stack client (which would be the preferred way) requires quite a bit of work, would making an IPv6-only "fork" be that hard? I've only taken a look on the surface level on the source code and appears code split wasn't immediately obvious to me.

comment:12 Changed 4 years ago by anonymous

There would need to be changes *everywhere* that deals with addresses. Making a dual-stack client would be no substantial extra work, but making it support IPv6 at all would.

comment:13 Changed 4 years ago by anonymous

No good news for the support of rtorrent to ipv6?

comment:14 Changed 4 years ago by anonymous

The lack of IPv6 is the only thing turning me away from rtorrent. So far deluge has all I want but it sounds like rtorrent may have a lower resource usage but since it lacks IPv6 it's not an option.

Also I don't see why bittorrent over a tunnel is moronic. It sounds more like a moronic comment to me...

Many tunnel providers are trying to convince people to use IPv6 so provide good bandwidth and limited or no traffic shaping which is more then can be said for many ISPs in many places. Of course if your ISP is shaping tunneled IPv6 it may not help much but they may not, particularly if it's local traffic (and quite a number of countries have local tunnel providers). And remember it cuts both ways. If you IPv6 connectivity is no worse and no better then you IPv4 even if tunneled, it could still help you if the seeder or (if you aren't a leecher who cares little about giving back) a leecher and the peer has decent better IPv6 connectivity then IPv4 (whether tunneled or native). Obviously you should abuse a free service but many tunnel providers are encouraging this sort of usage. Let's not forget that SixXs? a conglemerate of tunnel providers offer a IPv6 ONLY tracker with free seeding (obviously only for legal content). Finally if there are decent IPv6 peers particularly on a rare file, why not use them tunneled if that's the only option to you even if your IPv6 connectivity is worse then IPv4 it may still be better? The simple fact is, there are many good reasons why IPv6 whether tunneled or native provides advantages, if it's not added soon rtorrent is going to be left behind.

P.S. Let's not forget many people are using and paying for internet enabled 'VPNs' to get around traffic restrictions. Sometimes VPNs in far away countries. That's hardly moronic if it's the only way for them to get decent torrents. And if they don't care about latency (and bt isn't really latency sensitive) why not use the VPN that gives the best performance for the best price no matter what country? This may not be great for the internet but it's not their fault the system is so borked. And using IPv6 with a free tunnel broker that's in the same country in addition is obviously far better then that.

comment:15 Changed 4 years ago by anonymous

Still nothing to support IPV6 of rtorrent? May be so complicated to add a few lines of code to support what will be the standard ip of the future? This is a demanding little, and it is becoming essential to every day.

comment:16 Changed 4 years ago by anonymous

If it's so easy, why didn't you do it in 5 minutes already?

Fact is, adding IPv6 support in rtorrent is SIGNIFICANTLY more work than you expect. It's not just "a few lines of code" here and there. There are thousands of lines of code you'd have to review, to check if they break if the address family is now different (for instance because they attempt to store a network address in a 32-bit integer), in addition to writing new code for just about any function that uses networking. Many things will just not work in IPv6, like DHT which will require a modification to the protocol. So those need to make sure that they don't accidentally use IPv6 addresses/sockets. And all that without making the regular IPv4 code less efficient and buggier.

I estimate that if you were to pay someone to add IPv6 support, the number of hours of work required would likely not let you get away with under $500. Twice that would not be surprising either. And that's not even including fixing the inevitable bugs that will show up. So, how much is IPv6 support worth to you again?

comment:17 Changed 4 years ago by dimko

ipv6 would be handy, as for now i will have to look for something else

comment:18 Changed 4 years ago by ert

Having ipv6 would enable to workaround routers that block some trackers but only their ipv4 address.

comment:19 Changed 3 years ago by Steinar H. Gunderson

Here are IPv6 patches for current libtorrent/rtorrent. They're written by myself, and to the best of my knowledge will make rtorrent conform to BEP 7 ( http://www.bittorrent.org/beps/bep_0007.html).

 http://home.samfundet.no/~sesse/libtorrent-0.12.6-ipv6.patch  http://home.samfundet.no/~sesse/rtorrent-0.8.6-ipv6.patch

The changes can be summarized as follows:

  • rak (same changes in libtorrent and rtorrent): Extend the socket_address class to support IPv6 where needed, including string parsing.
  • libtorrent: Open an IPv6 socket if supported, and communicate with mapped-v4 addresses on that socket for IPv4. (I haven't actually checked if I can do without send()-ing to mapped-v4 addresses or not.)
  • libtorrent: Send IPv6 address (after a priority order, which prefers global addresses and discourages secondary/privacy addresses) in ipv6= header if not already sending an ip= header.
  • libtorrent: Support IPv6 addresses in compact (binary) format.
  • rtorrent: If a HTTP connection (e.g. to a tracker) fails due to name resolution problems, try once more over IPv6. (IOW, IPv6 connections are supported, but IPv4 connections are always preferred, since by far the easiest way to give the tracker our global IPv4 address is to connect to it over IPv4.)
  • rtorrent: Widen the IP field a bit in the peer list, and truncate IP addresses that are too long by replacing the overlong part with "...".

All changes are #ifdef-ed with RAK_USE_INET6. I've tested this lightly against different clients and trackers, and it generally seems to work about as well as the other clients I've tried. That doesn't mean there still can't be bugs, of course.

Possible caveats:

  • I haven't actually tried with --disable-ipv6, but I guess that will be caught pretty quickly.
  • I honestly don't know enough about the libtorrent ABI to say if this change warrants an ABI bump or not it or not, but I have the feeling it might. (Also, RAK_USE_INET6 might cause an ABI change, in which case rtorrent and libtorrent need to be compiled with the same --{enable,disable}-ipv6 option.)
  • I haven't tried compiling on anything but Linux, but I don't use anything non-POSIX (except the IPv6 address discovery, which has a POSIX fallback).
  • Privacy addresses could be handled more elegantly; in particular, when connecting to an IPv6 tracker we will most likely connect using a privacy address that may disappear between now and the next tracker connect. There are several ways of mitigating this (like watching the address and reconnect to the tracker once it goes away, binding to a non-privacy address when connecting, or binding to the address we gave the tracker to keep it from going away), but in practice the problem will be relatively small, especially as privacy addresses are pretty rare outside Windows.
  • The IPv6 DHT extension is not implemented.

BTW, whoever up in this thread claimed an rtorrent IPv6 patch must be a huge amount of work and cost at least $500... I'm not sure how much you've looked at rtorrent source before, but it wasn't. I'd gladly take $450, though, if you really want to pay =)

comment:20 Changed 3 years ago by josef

Nice work, although I'm sure you had to work for more than a few hours... maybe you're just underestimating your hourly worth ;)

Now to the comments... I haven't been able to compile it on either Linux or FreeBSD.

On Linux 2.6.28 (Kubuntu 9.10 x86_64) I get a compile error and some warnings:

local_addr.cc: In function ‘bool torrent::get_local_address(sa_family_t, rak::socket_address*)’:
local_addr.cc:206: warning: comparison between signed and unsigned integer expressions
local_addr.cc:208: warning: comparison between signed and unsigned integer expressions
local_addr.cc:225: error: ‘IFA_F_DADFAILED’ was not declared in this scope

It seems that the IFA_F_DADFAILED #define was added in a later kernel. You should probably add checks for all of them and default them if they do not exist.

Furthermore, s6_addr32 is not a posix member of in6_addr, on FreeBSD I get errors in socket_fd.cc and local_addr.cc, for instance:

socket_fd.cc:60: error: ‘const struct in6_addr’ has no member named ‘s6_addr32’

The only reliably defined member is uint8_t s6_addr.

Also, I think the dummy IPv6 for retrieving the local address (on systems other than Linux) should be in the documented example network, 2001:db8::/32, and the dummy IPv4 should be in 192.0.2.0/24. Or at least some other addresses that are guaranteed to never become valid addresses. Actually, the local address should perhaps be determined separately for each destination address, for multihomed setups with not just one default route.

Finally, you mention that the DHT ipv6 extension isn't implemented, are you going to work on that? Currently DHT is completely broken and produces an error message when trying to start it:

DHT error: Address not af_inet

And a question regarding this:

+AddressList::parse_address_compact_ipv6(const std::string& s) {
+  if (sizeof(const SocketAddressCompact6) != 18)
+    throw internal_error("ConnectionList::AddressList::parse_address_compact_ipv6(...) bad struct size.");
+
+  std::copy(reinterpret_cast<const SocketAddressCompact6*>(s.c_str()),
+           reinterpret_cast<const SocketAddressCompact6*>(s.c_str() + s.size() - s.size() % sizeof(SocketAddressCompact)),
+           std::back_inserter(*this));
+}

Shouldn't it be " % sizeof(SocketAddressCompact6)" instead of SocketAddressCompact?

comment:21 Changed 3 years ago by Steinar H. Gunderson

josef: Thanks for your comments. I'll try to respond as best as I can:

  • IFA_D_DADFAILED: Yes, this should have an #ifdef.
  • Lack of s6_addr32: I'm a bit surprised, but okay. :-)
  • 2001:db8::/32: The problem with this is that you're not really guaranteed to have a route there. For instance, on my router I have a full BGP table and thus no default route; 2001:db8::/32 simply not have a route entry, but 2001:700::/32 will definitely unless all Nordic universities drop off the IPv6 Internet entirely. (I considered using 2001::/32, but that's Teredo and would probably prefer a Teredo address, which is not good.) Another alternative would be the tracker's IPv6 address, but of course the tracker might not have IPv6. In any case, we can only give one ipv6= address here, so we can't really distinguish between multiple destinations.
  • DHT: OK, that's not good. I'll fix that later today.
  • SocketAddressCompact6: Nice catch. I'll update the patch.

comment:22 follow-up: ↓ 28 Changed 3 years ago by Steinar H. Gunderson

Here's an updated patch:

 http://home.samfundet.no/~sesse/libtorrent-0.12.6-ipv6-02.patch

No changes needed to rtorrent from the last patch. Changes:

  • IFA_D_* are not #ifdef-ed for one by one.
  • All use of s6_addr32 have been replaced by casts (where const) and memcpy (where not, so we won't get aliasing issues).
  • IPv4 DHT should now work properly. I haven't been able to find a tracker where there are IPv6 DHT clients; thus, I haven't done anything to DHT for IPv6.
  • The SocketAddressCompact6 typo has been fixed. Since 6 is a multiple of 18, I don't think it had much practical effect except for malformed replies (where it may have caused a theoretical security problem?).

Note that I'm not honestly sure if FreeBSD supports mapped-v4 on IPv6 sockets at all. If they don't, one would need to change into using separate v4 and v6 sockets, which would be more intrusive. I don't think we need to fix everything at the same time to get such a patch merged -- BSD users can simply use --disable-ipv6 and keep on going as before.

comment:23 Changed 3 years ago by tg@mirbsd.org

Ok, I was thinking “wanna have!!!” when I read it on Plänet Debian, but now I’m disappointed. Mapped-v4 addresses have been deprecated for quite a while due to “security concerns” I cannot fully grok, but I still use an OS without v4-mapped (and even on these with it, it’s turned OFF by default these days!) so your patch won’t enable IPv6 support for me but disable IPv4 support additionally ☹

comment:24 Changed 3 years ago by Steinar H. Gunderson

tg: Who's made this deprecation, and with what rationale? I'd be happy to get a reference.

FWIW, it's turned on by default in upstream Linux. Debian has changed it recently, mainly citing a desire for consistency between FreeBSD and Linux kernels.

comment:25 Changed 3 years ago by Steinar H. Gunderson

FWIW, the only reference I could find says that only OpenBSD has done this, and the relevant RFC seems to be RFC4942 ( http://www.ietf.org/rfc/rfc4942.txt) which pretty clearly says mapped-v4 addresses in APIs (as opposed to on the wire) are not deprecated (near the end of section 2.2).

If OpenBSD thinks this is a reasonable decision, by all means they are free to think so (although I respectfully disagree). I guess it's up to the rTorrent developer(s) to figure out if that should block this patch or not -- it's not hard to check for such behavior at configure time and disable IPv6 if so, so it should not cause any regressions.

comment:26 Changed 3 years ago by anonymous

They're not deprecated as such. It was a security consideration of OpenBSD to disallow dual-stack sockets, because it's possible that someone might write an app which fails to apply IPv4-based access rules correctly for mapped-ipv4 addresses. Yeah... not only do they take away the gun so you can't you shoot yourself in the foot, they also pad the foot so heavily that you can't even walk anymore. Sigh.

I doubt this is up for discussion, so you would need to have a facility for opening two sockets on OpenBSD, one for ipv4 and one for ipv6.

Does it work to compile with patch, but configure --disable-ipv6? Then the OpenBSD issue shouldn't be a blocker.

comment:27 Changed 3 years ago by Steinar H. Gunderson

anonymous: The patch should be a complete no-op for --disable-ipv6.

comment:28 in reply to: ↑ 22 Changed 3 years ago by josef

Replying to Steinar H. Gunderson:

  • IPv4 DHT should now work properly.

It still needed some work, because it assumed the family was af_inet and used the address accordingly. The IPV4 is used as key and hashing salt, so the easiest way to fix this was to translate mapped addresses, without that change it couldn't validate received packets and just discarded them. Currently it still can't process actual IPV6 packets however. Patch is at  http://ovh.ttdpatch.net/~jdrexler/rt/experimental/fix-dht-ipv6.diff

It would be useful if you could put the ipv4-from-ipv6 normalization from socket_fd.cc into rak::socket_address_inet6, though, I could've reused that code here.

comment:29 Changed 3 years ago by Steinar H. Gunderson

josef: I incorporated your fix, and pulled the mapped-v4 normalization into socket_address.h (for both rtorrent and libtorrent, although it's not used in libtorrent). Updated patches:

 http://home.samfundet.no/~sesse/rtorrent-0.8.6-ipv6-03.patch  http://home.samfundet.no/~sesse/libtorrent-0.12.6-ipv6-03.patch

comment:30 Changed 3 years ago by tg@mirbsd.org

Yes, on the wire is always bad, but in APIs I personally still don’t see the harm. The person from which it originated is dead (itojun-san), but OpenBSD has adopted it, NetBSD® too (disabled by default).

I expect it to work with --disable-ipv6 but that’s not a good solution.

It was quite some work though to get, for example, Fefe’s IPv6 patch for djbdns to be changed to use multiple sockets and address families…

comment:31 Changed 3 years ago by josef

OK, DHT works now, thanks.

For completeness sake I tried compiling with --disable-ipv6, and got three errors where sa_inet6 wasn't protected by an #ifdef:

../../../rak/socket_address.h:389: error: ‘sa_inet6’ was not declared in this scope
peer_list.cc:69: error: ‘const class rak::socket_address’ has no member named ‘sa_inet6’
peer_list.cc:70: error: ‘const class rak::socket_address’ has no member named ‘sa_inet6’

The first error also repeats for rtorrent.

Also, I'm of the opinion that if OpenBSD wants to have a broken IPv6 stack, it's their job to make apps work with it. If they want rtorrent to use ipv6 on their platform, they can go fix it themselves. Such standards-defying behaviour should not be encouraged and they need to be aware of the costs it would force upon others.

comment:32 follow-ups: ↓ 33 ↓ 59 Changed 3 years ago by anonymous

Actually, it only works on Linux, where I can a sockaddr_in to an IPv6 socket and Linux does the translation. But on *BSD that doesn't work, so the code you have in SocketFd::connect also needs to be refactored into socket_address. Maybe a socket_address_inet6::from_inet function.

Something else that *BSD is picky about, is that the last argument to sendto needs to be not just "big enough", but *exactly* the expected value, so the calls needs to be different for each protocol.

Here's how I got it to work in the meantime:  http://ovh.ttdpatch.net/~jdrexler/rt/experimental/fix-ipv6_socket_datagram.diff

comment:33 in reply to: ↑ 32 ; follow-up: ↓ 34 Changed 3 years ago by anonymous

Replying to anonymous:

Actually, it only works on Linux, where I can a sockaddr_in to an IPv6 socket and Linux does the translation. But on *BSD that doesn't work, so the code you have in SocketFd::connect also needs to be refactored into socket_address. Maybe a socket_address_inet6::from_inet function.

It's pretty easy separating this out. I'll do it.

Something else that *BSD is picky about, is that the last argument to sendto needs to be not just "big enough", but *exactly* the expected value, so the calls needs to be different for each protocol.

That can be fixed by just using length().

Here's how I got it to work in the meantime:  http://ovh.ttdpatch.net/~jdrexler/rt/experimental/fix-ipv6_socket_datagram.diff

I tried incorporating this patch, but it seems to be missing something -- m_ipv6_socket is not defined for SocketDatagram??

comment:34 in reply to: ↑ 33 ; follow-up: ↓ 35 Changed 3 years ago by josef

Replying to anonymous:

I tried incorporating this patch, but it seems to be missing something -- m_ipv6_socket is not defined for SocketDatagram?

Sorry, I forgot to mention, I renamed the dummy bool in Event to m_ipv6_socket.

Though I have to wonder why SocketFd isn't derived from SocketBase (and thus Event) in the first place. The Event<->SocketFd casts are pretty ugly.

comment:35 in reply to: ↑ 34 Changed 3 years ago by anonymous

Replying to josef:

Though I have to wonder why SocketFd isn't derived from SocketBase (and thus Event) in the first place. The Event<->SocketFd casts are pretty ugly.

Well, in general rtorrent uses casting way too much for my preference. It's extremely unobvious that you cannot add a member to SocketFd? without getting random data overwritten since the struct is a different size (that one took me a while to track down). That's not my decision, though, and I take it it is like that because someone in charge likes it that way. :-)

In any case, I've made updated patches -- they should fix compiling without IPv6, and I've pulled the mapped address conversion into rak. It also uses .length() a few places, so it might fix the remaining BSD DHT problems. It's untested except for compilation on Linux, though.

 http://home.samfundet.no/~sesse/libtorrent-0.12.6-ipv6-04.patch  http://home.samfundet.no/~sesse/rtorrent-0.8.6-ipv6-04.patch

comment:36 Changed 3 years ago by anonymous

I've just build and installed a patched version on Debian/Lenny? (amd64), seems to work so far, but there is a small cosmetic bug in the peer info view:

Address: 2001:db8:f001:f00d:0102:03ff:fe04:0506:36862

I think the IPv6-Address should probably be surounded by [] to make it distinguishable from the port info: [2001:db8:f001:f00d:0102:03ff:fe04:0506]:36862

comment:37 follow-up: ↓ 38 Changed 3 years ago by jakllsch@kollasch.net

SocketFd::set_priority() should have:

#ifdef RAK_USE_INET6
  if (m_ipv6_socket == true)
        return setsockopt(m_fd, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) == 0;
  else
#endif

Also, the s6_addr32 part of the sockaddr union is not standardized, and thus is not consistently available on all platforms, please use s6_addr instead. (Actually, if you don't mind referencing private elements it is possible. See CUPS's http.h for example.)

With those two things addressed, this works on NetBSD, to the limited extent I tested it.

comment:38 in reply to: ↑ 37 Changed 3 years ago by anonymous

Replying to jakllsch@…:

SocketFd::set_priority() should have:

#ifdef RAK_USE_INET6
  if (m_ipv6_socket == true)
        return setsockopt(m_fd, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) == 0;
  else
#endif

That's a compile error; there's no m_ipv6_socket member in SocketFd?. Did you really try this?

Also, the s6_addr32 part of the sockaddr union is not standardized, and thus is not consistently available on all platforms, please use s6_addr instead.

The patch hasn't used s6_addr32 for a long time (actually, since the first version); did you try an old version?

comment:39 Changed 3 years ago by Steinar H. Gunderson

Oh man.. there's actually two different SocketFd? definitions. :-/

comment:40 Changed 3 years ago by Steinar H. Gunderson

Okay, new versions:

 http://home.samfundet.no/~sesse/libtorrent-0.12.6-ipv6-05.patch  http://home.samfundet.no/~sesse/rtorrent-0.8.6-ipv6-05.patch

Changes since -04:

  • [address]:port is used in the peer view for IPv6 addresses.
  • The changes to libtorrent SocketFd? have been ported to rtorrent SocketFd?. (I don't know if this has any real effects, but it sounds like a bad idea to fork these further.)
  • set_priority uses IPV6_TCLASS for IPv6 sockets.

comment:41 Changed 3 years ago by anonymous

Thanks a lot for the patch Steinar!

I think -05 leaks socket fds on the tracker connection though. After patching rtorrent I get more and more entries like that in lsof:

lxbsc03:~/torrent# lsof -p pidof rtorrent -n | grep identify rtorrent 15491 root 6u sock 0,4 0t0 1151728627 can't identify protocol rtorrent 15491 root 11u sock 0,4 0t0 1151726788 can't identify protocol rtorrent 15491 root 12u sock 0,4 0t0 1151726931 can't identify protocol rtorrent 15491 root 13u sock 0,4 0t0 1151727325 can't identify protocol rtorrent 15491 root 15u sock 0,4 0t0 1151728604 can't identify protocol rtorrent 15491 root 30u sock 0,4 0t0 1151727957 can't identify protocol rtorrent 15491 root 33u sock 0,4 0t0 1151727480 can't identify protocol rtorrent 15491 root 41u sock 0,4 0t0 1151728355 can't identify protocol rtorrent 15491 root 49u sock 0,4 0t0 1151728116 can't identify protocol rtorrent 15491 root 57u sock 0,4 0t0 1151728369 can't identify protocol rtorrent 15491 root 96u sock 0,4 0t0 1151728583 can't identify protocol rtorrent 15491 root 103u sock 0,4 0t0 1151728564 can't identify protocol rtorrent 15491 root 110u sock 0,4 0t0 1151728574 can't identify protocol rtorrent 15491 root 126u sock 0,4 0t0 1151728595 can't identify protocol

I can force the list to grow by forcing tracker announcements (T). This affects both IPv4 and IPv6 trackers. I could not reproduce this using unpatched sources.

comment:42 Changed 3 years ago by anonymous

Sorry that looks ugly.

lxbsc03:~/torrent# lsof -p `pidof rtorrent` -n | grep identify
rtorrent 15491 root    6u  sock        0,4       0t0 1151728627 can't identify protocol
rtorrent 15491 root   10r  sock        0,4       0t0 1151729890 can't identify protocol
rtorrent 15491 root   11u  sock        0,4       0t0 1151726788 can't identify protocol
rtorrent 15491 root   12u  sock        0,4       0t0 1151726931 can't identify protocol
rtorrent 15491 root   13u  sock        0,4       0t0 1151727325 can't identify protocol
rtorrent 15491 root   15u  sock        0,4       0t0 1151728604 can't identify protocol
rtorrent 15491 root   22u  sock        0,4       0t0 1151730154 can't identify protocol
rtorrent 15491 root   23u  sock        0,4       0t0 1151730320 can't identify protocol
rtorrent 15491 root   26u  sock        0,4       0t0 1151730315 can't identify protocol
rtorrent 15491 root   30u  sock        0,4       0t0 1151727957 can't identify protocol
rtorrent 15491 root   33u  sock        0,4       0t0 1151727480 can't identify protocol
rtorrent 15491 root   41u  sock        0,4       0t0 1151728355 can't identify protocol
rtorrent 15491 root   49u  sock        0,4       0t0 1151728116 can't identify protocol
rtorrent 15491 root   57u  sock        0,4       0t0 1151728369 can't identify protocol
rtorrent 15491 root   96u  sock        0,4       0t0 1151728583 can't identify protocol
rtorrent 15491 root  103u  sock        0,4       0t0 1151728564 can't identify protocol
rtorrent 15491 root  110u  sock        0,4       0t0 1151728574 can't identify protocol
rtorrent 15491 root  126u  sock        0,4       0t0 1151728595 can't identify protocol

Eventually after a couple of hours the rtorrent process either blows up or stops transfering.

comment:43 Changed 3 years ago by anonymous

I can confirm that problem, although I haven't checked that they're tracker connections. Netstat doesn't show the sockets, I only see them with lsof and /proc/pidof rtorrent/fd. I see over 100 open sockets even with all torrents closed and no peers connected.

Anyway, tracker connections are handled by libcurl, so if they're really tracker connections then that would be a libcurl ipv6 bug. I still have libcurl 7.18.2, which is pretty old anyway. Maybe upgrading will help.

comment:44 Changed 3 years ago by Steinar H. Gunderson

Sounds like an issue in the fallback to IPv4 (I clone the HTTP entry; perhaps that leaks a socket fd). I'll take a look and see if I can reproduce it.

comment:45 Changed 3 years ago by anonymous

It leaks sockets, with just one IPv4-only tracker as well as with just one IPv6-only tracker.

Debian Testing amd64 -> libcurl 7.19.7

comment:46 Changed 3 years ago by Steinar H. Gunderson

OK, I found the leak -- it's the netlink socket I use to enumerate local addresses. Ironically enough I had remembered to close it on all error paths, but not the success path...

New patch set (no changes to rtorrent):

 http://home.samfundet.no/~sesse/libtorrent-0.12.6-ipv6-06.patch  http://home.samfundet.no/~sesse/rtorrent-0.8.6-ipv6-06.patch

comment:47 Changed 3 years ago by Bernhard Schmidt

Thank you very much, I can confirm that this seems to fix the leak.

I have built patched packages of -06 in my Ubuntu PPA at  https://launchpad.net/~berni/+archive/ipv6 . They do not work on Debian due to a rather nasty package split, I recompiled them on Debian Lenny for amd64 and i386. They can be found here:  http://users.birkenwald.de/~berni/temp/deb/

comment:48 follow-up: ↓ 49 Changed 3 years ago by Steinar H. Gunderson

rtorrent maintainers: Is there anything else you want me to do with this patch? Can it be merged into mainline?

comment:49 in reply to: ↑ 48 Changed 3 years ago by anonymous

Replying to Steinar H. Gunderson:

rtorrent maintainers: Is there anything else you want me to do with this patch? Can it be merged into mainline?

Yes, is it ready yet? I can't wait for it to merge and eventually make it to debian repo.

comment:50 follow-up: ↓ 51 Changed 3 years ago by anonymous

So I've applied the patch and built out a version of rtorrent that ostensibly supports IPv6. Using lsof, I confirmed that rtorrent's listen port was bound to IPv6, so it appears the patch was applied correctly and rtorrent was built out properly.

I then decided to try out one of SixXS' IPv6-only torrents. Unfortunately, when I added the .torrent file, the tracker returned the following error:

"We only accept direct connections, specifying the ip option thus is not accepted"

So... thoughts? :)

comment:51 in reply to: ↑ 50 ; follow-up: ↓ 52 Changed 3 years ago by Steinar H. Gunderson

Replying to anonymous:

I then decided to try out one of SixXS' IPv6-only torrents. Unfortunately, when I added the .torrent file, the tracker returned the following error:

"We only accept direct connections, specifying the ip option thus is not accepted"

So... thoughts? :)

IIRC SixXS' torrent service is broken -- their seeds are all offline. (I filed a ticket for it but was told it's not a supported service.)

I haven't seen that error before, though, and I'm unable to reproduce it. Connecting to  http://www.sixxs.net/tools/tracker/torrents/65e7d990b15ae4d3a1142dcbb15cb582a8863357.torrent I find one peer and downloading proceeds as usual. What's your configuration -- operating system? Type of IPv6 connectivity? Do other IPv6-only trackers (like the ones on  http://ipv6.torrent.ubuntu.com:6969/) work?

comment:52 in reply to: ↑ 51 ; follow-up: ↓ 53 Changed 3 years ago by anonymous

Replying to Steinar H. Gunderson:

Replying to anonymous:

I then decided to try out one of SixXS' IPv6-only torrents. Unfortunately, when I added the .torrent file, the tracker returned the following error:

"We only accept direct connections, specifying the ip option thus is not accepted"

So... thoughts? :)

IIRC SixXS' torrent service is broken -- their seeds are all offline. (I filed a ticket for it but was told it's not a supported service.)

I haven't seen that error before, though, and I'm unable to reproduce it. Connecting to  http://www.sixxs.net/tools/tracker/torrents/65e7d990b15ae4d3a1142dcbb15cb582a8863357.torrent I find one peer and downloading proceeds as usual. What's your configuration -- operating system? Type of IPv6 connectivity? Do other IPv6-only trackers (like the ones on  http://ipv6.torrent.ubuntu.com:6969/) work?

Ahah! After spending 15 minutes writing up a reply, I think I just figured out the problem. I'd mistakenly had the "ip:" setting defined in my .rtorrent.rc. That setting defines the IP that's reported to the tracker, and is useful if, for some reason, you need to explicitly tell the tracker what your external IP is.

Well, my guess is rtorrent was reporting that IPv4 IP to the tracker, even though I'm dual-stacked and have a local IPv6 address.

Sounds to me like this might be something that should be addressed, though I'm not sure how. Presumably rtorrent provides the tracker with both the IPv4 and IPv6 addresses, if the host is on a dual-stack machine. So I would think, if the "ip" option is specified, that should only affect the IPv4 address reported.

In principle, you could also add an "ip6" (or something) address option to override that value, as well, but given the whole point of such a setting is to work around NAT, and one of the main points of IPv6 is to make NAT obsolete, such a setting would be fairly pointless.

comment:53 in reply to: ↑ 52 Changed 3 years ago by anonymous

Replying to anonymous:

Ahah! After spending 15 minutes writing up a reply, I think I just figured out the problem. I'd mistakenly had the "ip:" setting defined in my .rtorrent.rc. That setting defines the IP that's reported to the tracker, and is useful if, for some reason, you need to explicitly tell the tracker what your external IP is.

Well, this is perfectly legal, and all the more important when you connect to the tracker over IPv6. The tracker will only get one of your IP addresses from the connection itself, so if you want it to use IPv4 as well you have to specify an ip= parameter. The fact that SixXS' tracker doesn't accept that is, well, not a bug in rtorrent.

Note that if you connect to a tracker over IPv4 (the default if the tracker supports it), rtorrent will include an ipv6= flag with the best local IPv6 address it can find.

comment:54 Changed 3 years ago by rakshasa

You got a stray bool variable in SocketFd? that shouldn't be there as the class is supposed to be equivalent to file descriptor integers. Also the bool thing in Event should be made into an int flag.

But send me a mail with the patches and a disclaimer that puts it under public domain for licensing purposes, and I'll review and/or make changes. Most likely only going to be minor changes before a commit.

comment:55 Changed 3 years ago by anonymous

Question about 'bind' option (aka) -b. I know some people use the 'bind' option, along with multihoming, for doing traffic shaping of rtorrent (the TOS flags don't seem to be set reliably, though that's a separate issue). I was going to fiddle around with this, but alas, it seems the -b option breaks things. If I try to bind to the existing interface on my machine using it's IPv4 address, I get:

Could not open/bind port for listening: Invalid argument

If I try to bind using the v6 address, I get:

Failed to parse command line option: Could not set bind address: Address family for hostname not supported.

And that's all without actually getting multihoming up and running. Is this expected behaviour?

comment:56 follow-up: ↓ 57 Changed 3 years ago by anonymous

As an aside, I'm not convinced that:

setsockopt(m_fd, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt))

is actually resulting in the TOS flag being set for IPv4 connections over a v6 socket (tcpdump indicates the tos flag is set to 0, even through an strace indicates that setsockopt is being called correctly).

Unfortunately, I can find little mention via Google of the IPV6_TCLASS socket option on Linux, so I have no idea where the problem actually lies (ie, is IPV6_TCLASS even supported (it should be, but...)? If so, is it expected to work for v4 addresses accessed over a v6 socket?).

comment:57 in reply to: ↑ 56 ; follow-up: ↓ 93 Changed 3 years ago by anonymous

Replying to anonymous:

As an aside, I'm not convinced that:

setsockopt(m_fd, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt))

is actually resulting in the TOS flag being set for IPv4 connections over a v6 socket (tcpdump indicates the tos flag is set to 0, even through an strace indicates that setsockopt is being called correctly).

Unfortunately, I can find little mention via Google of the IPV6_TCLASS socket option on Linux, so I have no idea where the problem actually lies (ie, is IPV6_TCLASS even supported (it should be, but...)? If so, is it expected to work for v4 addresses accessed over a v6 socket?).

And just to follow up on my own post, I've tested with stock rtorrent and the TOS flag is set correctly. This says to me that IPV6_TCLASS isn't supported for IPv4-mapped addresses (that's just a guess, though).

comment:58 Changed 3 years ago by anonymous

Thanks for this patch,it's great! Found some bugs: when configure --with-xmlrpc-c --enable-ipv6 and edit file .rtorrent.rc ,add this line: scgi_port = 127.0.0.1:5000 then run rtorrent , i got this error: rtorrent: Error in option file: ~/.rtorrent.rc:109: Could not prepare socket for listening: Invalid argument

comment:59 in reply to: ↑ 32 ; follow-up: ↓ 60 Changed 3 years ago by tg@mirbsd.org

Replying to anonymous:

Actually, it only works on Linux, where I can a sockaddr_in to an IPv6 socket and Linux does the translation. But on *BSD that doesn't work

Actually, on Debian unstable it wouldn’t, either, after the recent netbase upgrade which defaults to disabling this oft-criticised “feature”.

comment:60 in reply to: ↑ 59 Changed 3 years ago by anonymous

Replying to tg@…:

Actually, on Debian unstable it wouldn’t, either, after the recent netbase upgrade which defaults to disabling this oft-criticised “feature”.

This is wrong; the patch is tested and developed on Debian unstable with the bindv6only sysctl set to 1.

I don't necessarily agree with your assessment of dual-stack sockets as “oft-criticised”, by the way -- the only criticism I've seen of the concept come from people using or developing OpenBSD. In any case, I don't know how useful complaining about it further is; if you want to contribute code to accomodate OpenBSD's peculiarities, I'm sure it will be considered, but looking from the rest of the thread here I don't really think you'll be successful in getting others to do that work for you.

/* Steinar */

comment:61 Changed 3 years ago by Bernhard

All Debian does is to change the system-wide default of IPV6_V6ONLY to true, so applications don't have to deal with v4-mapped address when they are not ready to do so. See  http://lists.debian.org/debian-devel/2009/10/msg00541.html by Marco d'Itri (the Debian maintainer responsible for this change).

Applications are encouraged to set that socket option to whatever they expect. Steinar's patch does this in multiple locations

+ int zero = 0; + return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1;

so he's fine either way.

If OpenBSD does not implement this at all that's their problem. They could have just set that to 1 by default to work around the mild "security problems" introduced by users not expecting their v6-program to listen to v4.

comment:62 follow-up: ↓ 63 Changed 3 years ago by anonymous

ehhh... what's up doc?

comment:63 in reply to: ↑ 62 ; follow-ups: ↓ 65 ↓ 66 Changed 3 years ago by Steinar H. Gunderson

Replying to anonymous:

ehhh... what's up doc?

Upstream went silent. I'm still waiting for a response to my last e-mail with questions about how he wanted the patch adjusted.

/* Steinar */

comment:64 Changed 3 years ago by Basile

Does this patch compatible with xmlrpc (xmlrpc-c library)?

comment:65 in reply to: ↑ 63 Changed 3 years ago by rakshasa

Replying to Steinar H. Gunderson:

Upstream went silent. I'm still waiting for a response to my last e-mail with questions about how he wanted the patch adjusted.

Think I replied, however as I'm busy with other parts of the code I don't really have time to look closer at this.

comment:66 in reply to: ↑ 63 Changed 3 years ago by anonymous

Replying to Steinar H. Gunderson:

Upstream went silent. I'm still waiting for a response to my last e-mail with questions about how he wanted the patch adjusted.

please fix scgi_port/xmlrpc-c bug (http://libtorrent.rakshasa.no/ticket/1111#comment:58) first.

comment:67 Changed 3 years ago by anonymous

so this is dead in the water basically?

comment:68 Changed 3 years ago by rakshasa

It's not dead, just restin'.

comment:69 follow-up: ↓ 71 Changed 3 years ago by anonymous

who Can Help To fix this bug http://libtorrent.rakshasa.no/ticket/1111#comment:58

It's Very Important for me...

comment:70 Changed 3 years ago by anonymous

who Can Help To fix this bug

Use socket instead of host:port. It works for me, at least.

comment:71 in reply to: ↑ 69 Changed 3 years ago by Steinar H. Gunderson

comment:72 Changed 3 years ago by anonymous

This patch is for stable release of 0.8.6 or for svn? I have revision 1170 and libtorrent there lacks download.info.h ...

comment:73 Changed 3 years ago by anonymous

0.12.6 and 0.8.6 so its for stable release!

comment:74 Changed 3 years ago by anonymous

Yeah! It's work!

comment:75 follow-up: ↓ 76 Changed 3 years ago by emil@sandnabba.se

Anyone knows where download.info.h has gone?

Would be nice with IPv6 support even in SVN. :)

comment:76 in reply to: ↑ 75 Changed 3 years ago by anonymous

How you could not find one.

(note that atm svn head is fairly buggy anyway)

comment:77 Changed 3 years ago by li.e.00c@gmail.com

The tracker has both IPv4 and IPv6 addresses. I can connect to peers via IPv6, but connect to the tracker via IPv4. Is it a bug?

comment:78 Changed 3 years ago by Anssi Johansson

It appears that the priorities and the related comments in local_addr.cc (libtorrent) are slightly messed up.

IPv4:

//   2. Private address space (10.0.0.0/8, 172.16.0.0/16, 192.168.0.0/24)

should be

//   2. Private address space (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)

Relatedly,

  if ((addr.s_addr & htonl(0xff000000U)) == htonl(0x0a000000U) ||
      (addr.s_addr & htonl(0xffff0000U)) == htonl(0xac100000U) ||
      (addr.s_addr & htonl(0xffff0000U)) == htonl(0xc0a80000U)) {  
    return 2;

should be

  if ((addr.s_addr & htonl(0xff000000U)) == htonl(0x0a000000U) ||
      (addr.s_addr & htonl(0xfff00000U)) == htonl(0xac100000U) ||
      (addr.s_addr & htonl(0xffff0000U)) == htonl(0xc0a80000U)) {  
    return 2;

The priority list above the function lists 3 and 4 in a different order than in the code, ie. the comment says the function should return 3 for 0.0.0.0, but instead it returns 4.

IPv6:

//  1. Global address (2000::/16 not in 6to4 or Teredo)}}}

I think you meant 2000::/3. The code itself is fine, though.

comment:79 Changed 3 years ago by Matija Nalis

Any chance of releasing IPv6 enabled version soon?

Also, does anybody have some non-dead torrents (legal) which have IPv6-only tracker in them (so which could be used for testing how IPv6 rtorrent works in dual-stacked world)?

comment:80 Changed 3 years ago by Anssi Johansson

For what it's worth, I've been running an IPv6-enabled rtorrent for about a month now, with no IPv6-related problems (I encountered bug #2245, but that's probably not related). The box has sent 195GB of data over IPv6 (and 2300GB of data over IPv4). It even seems to work fine with wtorrent.

As for IPv6 trackers, see  http://ipv6.torrent.ubuntu.com/

comment:81 Changed 2 years ago by anonymous

The above patches are Steinar's updated for libtorrent-0.12.7 / rtorrent-0.8.7 with Anssi's corrections and a couple ifdefs so that it compiles on Nexenta/OpenSolaris?.

comment:82 Changed 2 years ago by anonymous

I need the last patches for rtorrent 0.8.6 / libtorrent 0.12.6 (stable version). @Steinar H. Gunderson can u please provide it.

comment:83 Changed 2 years ago by Steinar H. Gunderson

FWIW, I'm going to declare the “-08” patch set (posted by someone anonymous) as broken. It breaks IPv4 DHT since a hunk just disappeared from the patch, it misindents things in local_addr.cc, and it mashes changes to get rtorrent to work on Solaris (which should be in a completely different patch) into the IPv6 stuff. I don't have the time right now to make a fixed patch, but beware.

Changed 2 years ago by anonymous

Changed 2 years ago by anonymous

comment:84 follow-up: ↓ 87 Changed 2 years ago by alex k

Another "-08" patch set for rtorrent 0.8.7/libtorrent0.12.7. :) Added "bind","ip","scgi_port" (actually scgi does not work for last 0.12.7 from downloads, use SVN) options. CURLOPT_IPRESOLVE changed to CURL_IPRESOLVE_WHATEVER. ipv6 ip ranges and DHT no implemented. I'm not sure it's all correct, but works for me for 2 weeks.

comment:85 Changed 2 years ago by Vidar Hoel <vidar.hoel@sysrq.info>

Does the -08-patches, submitted 7 weeks ago, work? Because 3 months ago Steinar said they were broken, but how could he tell?? I mean, did he look into the future? :-)

comment:86 Changed 2 years ago by anonymous

AFAIK 0.8.8 already has IPv6 support

comment:87 in reply to: ↑ 84 Changed 2 years ago by alex k

Replying to alex k:

Another "-08" patch set for rtorrent 0.8.7/libtorrent0.12.7. :) Added "bind","ip","scgi_port" (actually scgi does not work for last 0.12.7 from downloads, use SVN) options. CURLOPT_IPRESOLVE changed to CURL_IPRESOLVE_WHATEVER. ipv6 ip ranges and DHT no implemented. I'm not sure it's all correct, but works for me for 2 weeks.

08-patches was uploaded by me and surprisingly erased old -08 set. I am sorry, it was an accident:). After that somebody 'purified' a base and erased the message from anonymous which upload old patches. Patches works for me and does not consist "mashes changes to get rtorrent to work on Solaris". And I did't find any sign of IPv6 support in 0.8.8. (Patchs applied pretty fine, but I have not tried build it).

comment:88 Changed 23 months ago by anonymous

can i haz ipv6 upstream plzplz?

comment:89 follow-up: ↓ 90 Changed 23 months ago by debo

I have a maybe stupid question:

If ipv6 support hasn't been integrated into the source tree, what feature does the configure option '--enable-ipv6' provide?

comment:90 in reply to: ↑ 89 Changed 23 months ago by alex k

Replying to debo:

I have a maybe stupid question:

If ipv6 support hasn't been integrated into the source tree, what feature does the configure option '--enable-ipv6' provide?

The option without patch include some common definitions, probably for future use. Nothing about use ipv6 in the ingine.

comment:91 follow-up: ↓ 92 Changed 23 months ago by anonymous

@alex k or/and Steinar H. Gunderson does rtorrent-0.8.7-ipv6-08.patch libtorrent-0.12.7-ipv6-08.patch also works with 0.8.9 without problems?

comment:92 in reply to: ↑ 91 Changed 22 months ago by alex k

Replying to anonymous:

@alex k or/and Steinar H. Gunderson does rtorrent-0.8.7-ipv6-08.patch libtorrent-0.12.7-ipv6-08.patch also works with 0.8.9 without problems?

Looks like works.

comment:93 in reply to: ↑ 57 ; follow-up: ↓ 94 Changed 22 months ago by nemozny@gmail.com

Replying to anonymous:

Replying to anonymous:

As an aside, I'm not convinced that:

setsockopt(m_fd, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt))

is actually resulting in the TOS flag being set for IPv4 connections over a v6 socket (tcpdump indicates the tos flag is set to 0, even through an strace indicates that setsockopt is being called correctly).

Unfortunately, I can find little mention via Google of the IPV6_TCLASS socket option on Linux, so I have no idea where the problem actually lies (ie, is IPV6_TCLASS even supported (it should be, but...)? If so, is it expected to work for v4 addresses accessed over a v6 socket?).

And just to follow up on my own post, I've tested with stock rtorrent and the TOS flag is set correctly. This says to me that IPV6_TCLASS isn't supported for IPv4-mapped addresses (that's just a guess, though).

Well, hello, I am a bit slower in thinking, does it mean that TOS/DSCP marking has been removed due to IPv6? Because I am really attached to that. I've looked to latest sources (0.8.9) and found TOS in command_network.cc but not in main.cc (config). Is it purpose or should I start panicking (anyway)?

comment:94 in reply to: ↑ 93 Changed 22 months ago by anonymous

Replying to nemozny@…:

Replying to anonymous:

Replying to anonymous:

As an aside, I'm not convinced that:

setsockopt(m_fd, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt))

is actually resulting in the TOS flag being set for IPv4 connections over a v6 socket (tcpdump indicates the tos flag is set to 0, even through an strace indicates that setsockopt is being called correctly).

Unfortunately, I can find little mention via Google of the IPV6_TCLASS socket option on Linux, so I have no idea where the problem actually lies (ie, is IPV6_TCLASS even supported (it should be, but...)? If so, is it expected to work for v4 addresses accessed over a v6 socket?).

And just to follow up on my own post, I've tested with stock rtorrent and the TOS flag is set correctly. This says to me that IPV6_TCLASS isn't supported for IPv4-mapped addresses (that's just a guess, though).

Well, hello, I am a bit slower in thinking, does it mean that TOS/DSCP marking has been removed due to IPv6? Because I am really attached to that. I've looked to latest sources (0.8.9) and found TOS in command_network.cc but not in main.cc (config). Is it purpose or should I start panicking (anyway)?

Sorry, I forgot to mention, rtorrent says to me, that he does not know the "tos" .rtorrent.rc option.

Note: See TracTickets for help on using tickets.