UdpSocket::set_ttl does not set IPv6 hoplimit field

8dcff7b
Opened by Alex Egger at 2022-03-31 20:13:04

It is not possible to set a hoplimit in an IPv6 packet sent over UDP. UdpSocket::set_ttl does not modify the hoplimit in the IPv6 packet and there seems to be no other way to do so.

I tried this code:

use std::net::{Ipv6Addr, SocketAddrV6, UdpSocket};

fn main() {
    let laddr = SocketAddrV6::new(Ipv6Addr::new(0,0,0,0,0,0,0,1), 50000, 0, 0);
    let destination = SocketAddrV6::new(Ipv6Addr::new(0,0,0,0,0,0,0,1), 50000, 0, 0);

    let socket = UdpSocket::bind(laddr).unwrap();
    socket.connect(destination).unwrap();
    socket.set_ttl(10).unwrap();
    println!("{:?}", socket.ttl().unwrap());

    let payload = [1,2,3,4,5,6,7,8];
    socket.send(&payload).unwrap();
}

I expected to see this happen: Since UdpSocket has no other function that would set the hoplimit in an IPv6 packet, I believe set_ttl should be doing this. I expected to capture a UDP packet with an IPv6 hoplimit field of 10.

Instead, this happened: The output of the program is as expected:

10

I used tcpdump -v -i lo udp port 50000 to capture the packet:

tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
23:43:02.146680 IP6 (flowlabel 0x487a1, hlim 64, next-header UDP (17) payload length: 16) localhost.localdomain.50000 > localhost.localdomain.50000: [bad udp cksum 0x0023 -> 0x6917!] UDP, length 8

The hoplimit field of the packet is still set to the default value of 64.

Meta

rustc --version --verbose:

rustc 1.23.0
binary: rustc
commit-hash: unknown
commit-date: unknown
host: x86_64-unknown-linux-gnu
release: 1.23.0
LLVM version: 4.0
  1. It is not possible to set a hoplimit in an IPv6 packet sent over UDP. UdpSocket::set_ttl does not modify the hoplimit in the IPv6 packet and there seems to be no other way to do so.

    I tried this code:

    use std::net::{Ipv6Addr, SocketAddrV6, UdpSocket};
    
    fn main() {
        let laddr = SocketAddrV6::new(Ipv6Addr::new(0,0,0,0,0,0,0,1), 50000, 0, 0);
        let destination = SocketAddrV6::new(Ipv6Addr::new(0,0,0,0,0,0,0,1), 50000, 0, 0);
    
        let socket = UdpSocket::bind(laddr).unwrap();
        socket.connect(destination).unwrap();
        socket.set_ttl(10).unwrap();
        println!("{:?}", socket.ttl().unwrap());
    
        let payload = [1,2,3,4,5,6,7,8];
        socket.send(&payload).unwrap();
    }
    

    I expected to see this happen: Since UdpSocket has no other function that would set the hoplimit in an IPv6 packet, I believe set_ttl should be doing this. I expected to capture a UDP packet with an IPv6 hoplimit field of 10.

    Instead, this happened: The output of the program is as expected:

    10
    

    I used tcpdump -v -i lo udp port 50000 to capture the packet:

    tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
    23:43:02.146680 IP6 (flowlabel 0x487a1, hlim 64, next-header UDP (17) payload length: 16) localhost.localdomain.50000 > localhost.localdomain.50000: [bad udp cksum 0x0023 -> 0x6917!] UDP, length 8
    

    The hoplimit field of the packet is still set to the default value of 64.

    Meta

    rustc --version --verbose:

    rustc 1.23.0
    binary: rustc
    commit-hash: unknown
    commit-date: unknown
    host: x86_64-unknown-linux-gnu
    release: 1.23.0
    LLVM version: 4.0
    
    <!-- TRIAGEBOT_START --> <!-- TRIAGEBOT_ASSIGN_START --> <!-- TRIAGEBOT_ASSIGN_DATA_START$${"user":"kckeiks"}$$TRIAGEBOT_ASSIGN_DATA_END --> <!-- TRIAGEBOT_ASSIGN_END --> <!-- TRIAGEBOT_END -->

    rustbot at 2022-03-03 19:36:52

  2. set_ttl maps directly to setsockopt with the IP_TTL argument. If you want to set the IPv6 hop limit we should add a method that does that.

    Steven Fackler at 2018-01-24 23:22:14

  3. @rustbot claim

    M. Meier at 2022-03-03 19:36:51

  4. On macOS Big Sur (11.6.5) using the exact snippet from the issue description is actually failing for me with the following output:

    thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 22, kind: InvalidInput, message: "Invalid argument" }', src/main.rs:9:24
    

    I was able to verify the same behaviour for TcpSocket.

    I think at least the documentation on set_ttl should document possible error conditions and should state that this only intended to work on ipv4 sockets.

    Should I report this as a separate issue?

    Matthias Wahl at 2022-03-31 20:07:58

  5. I would say, yes. This issue is for adding functionality.

    M. Meier at 2022-03-31 20:13:04