From 9de61aa69eb808d6fba84c9664dd8b5d6a15d6c8 Mon Sep 17 00:00:00 2001 From: duB Date: Tue, 10 Jul 2018 12:55:40 -0400 Subject: [PATCH] Fix IP options (TTL and ToS) on IPv6 sockets (#423) * set IPv6_UNICAST_HOPS when setting SRTO_IPTTL on IPv6 socket set IPV6_TCLASS when setting SRTO_TOS on IPv6 socket --- docs/API.md | 6 +++-- srtcore/channel.cpp | 55 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/docs/API.md b/docs/API.md index 5a9a9417d..fc0c6ebbc 100644 --- a/docs/API.md +++ b/docs/API.md @@ -446,7 +446,8 @@ inside the library. | --------------------- | ----- | ------- | --------- | ------ | ------------------ | ------ | | `SRTO_IPTOS` | 1.0.5 | pre | `int32_t` | | (platform default) | 0..255 | -- IP Type of Service (see IP_TOS option for UDP). Applies to sender only. +- IPv4 Type of Service (see IP_TOS option for IP) or IPv6 Traffic Class (see IPV6_TCLASS +of IPv6) depending on socket address family. Applies to sender only. - *Sender: user configurable, default: 0xB8* --- @@ -465,7 +466,8 @@ regular development.* | --------------------- | ----- | ------- | --------- | ------ | ------------------ | ------ | | `SRTO_IPTTL` | 1.0.5 | pre | `int32_t` | hops | (platform default) | 1..255 | -- IP Time To Live (see IP_TTL option for UDP). Applies to sender only. +- IPv4 Time To Live (see IP_TTL option for IP) or IPv6 unicast hops (see IPV6_UNICAST_HOPS for +IPV6) depending on socket address family. Applies to sender only. - *Sender: user configurable, default: 64* --- diff --git a/srtcore/channel.cpp b/srtcore/channel.cpp index e4af2c6c3..6edbd6d2f 100644 --- a/srtcore/channel.cpp +++ b/srtcore/channel.cpp @@ -100,8 +100,8 @@ m_iIPversion(AF_INET), m_iSockAddrSize(sizeof(sockaddr_in)), m_iSocket(), #ifdef SRT_ENABLE_IPOPTS -m_iIpTTL(-1), -m_iIpToS(-1), +m_iIpTTL(-1), /* IPv4 TTL or IPv6 HOPs [1..255] (-1:undefined) */ +m_iIpToS(-1), /* IPv4 Type of Service or IPv6 Traffic Class [0x00..0xff] (-1:undefined) */ #endif m_iSndBufSize(65536), m_iRcvBufSize(65536) @@ -198,13 +198,32 @@ void CChannel::setUDPSockOpt() #endif #ifdef SRT_ENABLE_IPOPTS - if ((-1 != m_iIpTTL) - && (0 != ::setsockopt(m_iSocket, IPPROTO_IP, IP_TTL, (const char*)&m_iIpTTL, sizeof(m_iIpTTL)))) - throw CUDTException(MJ_SETUP, MN_NORES, NET_ERROR); - - if ((-1 != m_iIpToS) - && (0 != ::setsockopt(m_iSocket, IPPROTO_IP, IP_TOS, (const char*)&m_iIpToS, sizeof(m_iIpToS)))) - throw CUDTException(MJ_SETUP, MN_NORES, NET_ERROR); + if (-1 != m_iIpTTL) + { + if(m_iIPversion == AF_INET) + { + if(0 != ::setsockopt(m_iSocket, IPPROTO_IP, IP_TTL, (const char*)&m_iIpTTL, sizeof(m_iIpTTL))) + throw CUDTException(MJ_SETUP, MN_NORES, NET_ERROR); + } + else //Assuming AF_INET6 + { + if(0 != ::setsockopt(m_iSocket, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (const char*)&m_iIpTTL, sizeof(m_iIpTTL))) + throw CUDTException(MJ_SETUP, MN_NORES, NET_ERROR); + } + } + if (-1 != m_iIpToS) + { + if(m_iIPversion == AF_INET) + { + if(0 != ::setsockopt(m_iSocket, IPPROTO_IP, IP_TOS, (const char*)&m_iIpToS, sizeof(m_iIpToS))) + throw CUDTException(MJ_SETUP, MN_NORES, NET_ERROR); + } + else //Assuming AF_INET6 + { + if(0 != ::setsockopt(m_iSocket, IPPROTO_IPV6, IPV6_TCLASS, (const char*)&m_iIpToS, sizeof(m_iIpToS))) + throw CUDTException(MJ_SETUP, MN_NORES, NET_ERROR); + } + } #endif timeval tv; @@ -271,14 +290,28 @@ void CChannel::setRcvBufSize(int size) int CChannel::getIpTTL() const { socklen_t size = sizeof(m_iIpTTL); - ::getsockopt(m_iSocket, IPPROTO_IP, IP_TTL, (char *)&m_iIpTTL, &size); + if (m_iIPversion == AF_INET) + { + ::getsockopt(m_iSocket, IPPROTO_IP, IP_TTL, (char *)&m_iIpTTL, &size); + } + else + { + ::getsockopt(m_iSocket, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (char *)&m_iIpTTL, &size); + } return m_iIpTTL; } int CChannel::getIpToS() const { socklen_t size = sizeof(m_iIpToS); - ::getsockopt(m_iSocket, IPPROTO_IP, IP_TOS, (char *)&m_iIpToS, &size); + if(m_iIPversion == AF_INET) + { + ::getsockopt(m_iSocket, IPPROTO_IP, IP_TOS, (char *)&m_iIpToS, &size); + } + else + { + ::getsockopt(m_iSocket, IPPROTO_IPV6, IPV6_TCLASS, (char *)&m_iIpToS, &size); + } return m_iIpToS; }