Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IPv6 Bind failures

I have a server implementation where I need 2 separate sockets - 1 IPv4 socket socket listening on a particular IPv4 address and server port X, and an IPv6 socket listening on a particular IPv6 address and same server port X. The IPv4 and IPv6 addresses are on the same interface.

    memset(&sin, 0, sizeof(sin));
    sin.sin_family      = AF_INET;
    sin.sin_addr.s_addr = htonl(v4addr);
    sin.sin_port        = htons(tcp_port);

I am using evconnlistener_new_bind to create ipv4 socket and bind to it. For IPv6 listener, the code is as below.

    memset(&sin6, 0, sizeof(sin6));
    sin6.sin6_family      = AF_INET6;
    memcpy(sin6.sin6_addr.s6_addr, v6addr_bytes, IPV6_ADDR_LEN);
    sin6.sin6_port        = htons(tcp_port);

    fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
    evutil_make_socket_nonblocking(fd)
    setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&on, sizeof(on))
    setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&on, sizeof(on))
    evutil_make_listen_socket_reuseable(fd)   /* Libevent call to set SO_REUSEADDR */
    evutil_make_socket_nonblocking(fd)        /* Libevent call to set fd non-blocking */ 
    bind(fd, (const struct sockaddr *)&sin6, sizeof(sin6))

As I bind my fd to the particular ipv6 address, I see a bind failure intermittently.

bind v6 failed sin6 3ffe::a00:513 - errno 99 - Cannot assign requested address

I tried to gdb in, but every time I gdb in, the bind succeeds.

I am not sure why I am seeing this problem. Can someone please help?

like image 993
shrejal Avatar asked Dec 04 '14 13:12

shrejal


1 Answers

By default, after a socket is bound to a TCP port, the port remains reserved for one minute when the socket is closed — this is called the TCP TIME_WAIT state. TIME_WAIT avoids some race conditions that could cause data corruption, but it is usually safe to ignore TIME_WAIT on the server side.

This is done by setting the SO_REUSEADDR socket option:

int one = 1;
rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))
like image 126
jch Avatar answered Sep 28 '22 01:09

jch