bind(): "Cannot assign request address"


I am aware of bind: cannot assign requested address and Cannot assign requested address – possible causes?, I have not been able to derive a solution from these.

I am trying to create a TCP stream (specifically here a std::net::TcpListener) directly with libc. I am encountering the error Cannot assign requested address and error code: 99 when running my code.

The exact output being:

error message: error code: : Cannot assign requested address
thread 'main' panicked at 'error code: 99', src/
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

My code (playground):

use libc; // 0.2.136

use std::mem::{size_of, transmute};

fn main() {
    // Create socket
    let socket_fd = unsafe {
        let socket = libc::socket(libc::AF_INET6, libc::SOCK_STREAM | libc::SOCK_NONBLOCK, 0);
        assert_ne!(socket, -1);
        let optval = 1i32;
        let res = libc::setsockopt(
            (&optval as *const i32).cast(),
        assert_eq!(res, 0);

    // Bind socket
    // decimal -> hexadecimal 007f.0000.0000.0001
    let sin6_addr = unsafe { transmute::<_, libc::in6_addr>(*b"007f000000000001") };
    let socket_address = libc::sockaddr_in6 {
        sin6_family: libc::AF_INET6 as u16,
        sin6_port: 8080,
        sin6_flowinfo: u32::default(),
        sin6_scope_id: u32::default(),
    let socket_address_length = size_of::<libc::sockaddr_in6>() as u32;
    unsafe {
        let res = libc::bind(
            (&socket_address as *const libc::sockaddr_in6).cast(),
        if res == -1 {
            let err = errno();
            print_error("error message: ");
            panic!("error code: {err}");
    assert_eq!(unsafe { libc::close(socket_fd) },0);

fn print_error(s: &str) {
    unsafe {
fn errno() -> i32 {
    unsafe { *libc::__errno_location() }

I set the option SO_REUSEPORT here as I need to create a stream that multiple processes can listen to.

The basic concept of SO_REUSEPORT is simple enough. Multiple servers (processes or threads) can bind to the same port

The port does not appear to be in use:

[email protected]:~$ sudo lsof -i -P -n
systemd-r  793 systemd-resolve   13u  IPv4  19452      0t0  UDP 
systemd-r  793 systemd-resolve   14u  IPv4  19453      0t0  TCP (LISTEN)
avahi-dae  855           avahi   12u  IPv4  31377      0t0  UDP *:5353 
avahi-dae  855           avahi   13u  IPv6  31378      0t0  UDP *:5353 
avahi-dae  855           avahi   14u  IPv4  31379      0t0  UDP *:49594 
avahi-dae  855           avahi   15u  IPv6  31380      0t0  UDP *:58397 
NetworkMa  859            root   36u  IPv4  36212      0t0  UDP> 
NetworkMa  859            root   37u  IPv4 110801      0t0  UDP> 
tor       1038      debian-tor    6u  IPv4  31407      0t0  TCP (LISTEN)
rust-anal 4117        jonathan   46u  IPv4  33176      0t0  UDP> 
rust-anal 4189        jonathan   46u  IPv4  33176      0t0  UDP> 
firefox   4297        jonathan    3u  IPv4 112786      0t0  TCP> (ESTABLISHED)
firefox   4297        jonathan   29u  IPv4 100032      0t0  TCP> (ESTABLISHED)
firefox   4297        jonathan   56u  IPv4 115182      0t0  TCP> (ESTABLISHED)
firefox   4297        jonathan   75u  IPv4  95741      0t0  TCP> (ESTABLISHED)
firefox   4297        jonathan   81u  IPv4  67879      0t0  TCP> (ESTABLISHED)
firefox   4297        jonathan  116u  IPv4 111739      0t0  TCP> (ESTABLISHED)
firefox   4297        jonathan  121u  IPv4  95751      0t0  TCP> (ESTABLISHED)
firefox   4297        jonathan  129u  IPv4 102073      0t0  TCP> (ESTABLISHED)
firefox   4297        jonathan  136u  IPv4  96742      0t0  TCP> (ESTABLISHED)
firefox   4297        jonathan  139u  IPv4  97943      0t0  TCP> (ESTABLISHED)
firefox   4297        jonathan  144u  IPv4  99520      0t0  TCP> (ESTABLISHED)
firefox   4297        jonathan  157u  IPv4 104859      0t0  TCP> (ESTABLISHED)
[email protected]:~$ 


You are transmuting b"007f000000000001" into a libc::in6_addr. But I don’t thing that is the proper thing to do.

Looking at the man page, that struct is:

struct in6_addr {
   uint8_t   s6_addr[16];

That is, just 16 bytes, the proper thing for an IPv6. But your bytes are actually the ASCII values of that string: 30303766..., that while technically an IPv6 address, it is not a local one of yours so you cannot bind to it.

Moreover, in IPv6 the proper localhost address is ::1, not That is 15 zeros followed by a single one.

If you want to bind to the IPv6 localhost by using a transmute that would be:

let sin6_addr = unsafe { transmute::<_, libc::in6_addr>([0_u8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]) };

Or if you insist on using a literal string (why?):

let sin6_addr = unsafe { transmute::<_, libc::in6_addr>(*b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01") };

Answered By – rodrigo

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published