Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not able to create IPv6 raw socket #517

Closed
jjnicola opened this issue Jun 17, 2024 · 4 comments · Fixed by #518
Closed

Not able to create IPv6 raw socket #517

jjnicola opened this issue Jun 17, 2024 · 4 comments · Fixed by #518

Comments

@jjnicola
Copy link
Contributor

I have the following function (also one for IPv4 with the IPV4 domain, which works as expected)

fn new_raw_ipv6_socket() -> Result<Socket, FunctionErrorKind> {
    match Socket::new(
        Domain::IPV6, // 10
        socket2::Type::RAW, // 3
        Some(Protocol::from(IPPROTO_RAW)), // 255
    ) {
        Ok(s) => Ok(s),
        Err(e) => Err(FunctionErrorKind::Dirty(format!(
            "new_raw_ipv6_socket: Not possible to create a raw socket: {}",
            e
        ))),
    }
}

If I call the function and try to set an option:

    let soc = new_raw_ipv6_socket()?; // do not fails here

    if let Err(e) = soc.set_header_included(true) { // It fails here
        return Err(FunctionErrorKind::Dirty(format!(
            "Not possible to create a raw socket: {}",
            e
        )));
    };

I get the following error:

send_v6packet: Not possible to create a raw socket: Protocol not available (os error 92)

Is this a bug or I am doing something wrong? This is working as expected in the program written in C. So, I discard some permission issue or OS issue. Thanks in advance.

@Thomasdezeeuw
Copy link
Collaborator

Quick search through the Linux code (https://github.com/search?q=repo%3Atorvalds%2Flinux+IP_HDRINCL&type=code) it seems that IP_HDRINCL (used by set_header_included) is IPv4 only?

But I don't use raw socket myself, so this could be a red herring.

@jjnicola
Copy link
Contributor Author

jjnicola commented Jun 17, 2024

it seems that IP_HDRINCL (used by set_header_included) is IPv4 only?

Thanks for the hint. But strange. The C code works without errors.

  soc = socket (AF_INET6, SOCK_RAW, IPPROTO_RAW);
  if (soc < 0)
    return NULL;

  if (setsockopt (soc, IPPROTO_IPV6, IP_HDRINCL, (char *) &opt_on,
                  sizeof (opt_on))
      < 0)
    perror ("setsockopt");

In that code, of course I don't get an error.

@Thomasdezeeuw
Copy link
Collaborator

Thanks for the hint. But strange. The C code works without errors.

The difference is that your C code uses IPPROTO_IPV6, where as header_included uses IPPROTO_IP (Ipv4):

socket2/src/socket.rs

Lines 1151 to 1156 in 6a13053

pub fn header_included(&self) -> io::Result<bool> {
unsafe {
getsockopt::<c_int>(self.as_raw(), sys::IPPROTO_IP, sys::IP_HDRINCL)
.map(|included| included != 0)
}
}

I think that's the problem.

We should split header_included into header_included_v4 and header_included_v6 to fix this.

@jjnicola
Copy link
Contributor Author

Thanks! I have test your suggestion and it worked. I have prepare a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants