[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [BUG] ssh_bind_listen() does not fail in windows when port is in use


I found a workaround.

In my code I created a similar bind_socket() function:
/* This is a copy to libssh bind_socket() but without setting SO_REUSEADDR
    so we can detect when an port is in use*/
socket_t SSHServer::bind_socket_non_reuse(ssh_bind sshbind, const char*
hostname,
    int port) {
    char port_c[6];
    struct addrinfo* ai;
    struct addrinfo hints;
    int opt = 1;
    socket_t s;
    int rc;

    memset(&hints, 0, sizeof(hints));

    hints.ai_flags = AI_PASSIVE;
    hints.ai_socktype = SOCK_STREAM;

    snprintf(port_c, 6, "%d", port);
    rc = getaddrinfo(hostname, port_c, &hints, &ai);
    if (rc != 0) {
        return SSH_INVALID_SOCKET;
    }

    s = socket(ai->ai_family,
        ai->ai_socktype,
        ai->ai_protocol);
    if (s == SSH_INVALID_SOCKET) {
        freeaddrinfo(ai);
        return SSH_INVALID_SOCKET;
    }

    // this is the part that I deleted
    //if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
    //    (char*)& opt, sizeof(opt)) < 0) {
    //   /* ssh_set_error(sshbind,
    //        SSH_FATAL,
    //        "Setting socket options failed: %s",
    //        strerror(errno));*/
    //    freeaddrinfo(ai);
    //    CLOSE_SOCKET(s);
    //    return -1;
    //}

    if (bind(s, ai->ai_addr, ai->ai_addrlen) != 0) {
        freeaddrinfo(ai);
        CLOSE_SOCKET(s);
        return SSH_INVALID_SOCKET;
    }

    freeaddrinfo(ai);
    if (listen(s, 10) < 0) {
        CLOSE_SOCKET(s);
        return SSH_INVALID_SOCKET;
    }

    return s;
}

Is like the original one but without setsockopt() setting SO_REUSEADDR and
calling listen() at the end (just as ssh_bind_listen() does).

And from the main code:

    ssh_session session;
    /* Create and configure the ssh session. */
    ssh_bind sshbind = ssh_bind_new();

    ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, ip);
    ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT, &port);
    ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY,
&verbosity);
    ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY_MEMORY,
priv_key.c_str()); // loads keys from memory

    socket_t fd = bind_socket_non_reuse(sshbind, ip, port);

    if (fd == SSH_INVALID_SOCKET){
        debug("Error listening to socket: %s\n", ssh_get_error(sshbind));
        exit(1);
    }

    ssh_bind_set_fd(sshbind, fd);

This way I set my own fd which does not have SO_REUSEADDR set in it.

On Thu, Mar 21, 2019 at 4:40 PM <g4-lisz@xxxxxxxxxxxx> wrote:

> On 22.03.19 00:15, Alberto Garcia wrote:
> > The socket has the SO_REUSEADDR so it does not fail when it is in use.
> > I don't know why that's set. Does anyone knows what is the intention
> > of it?
>
> Look here:
>
> https://stackoverflow.com/questions/577885/what-are-the-use-cases-of-so-reuseaddr
>
> I think it's for the reason the guy there explains: To be able to
> reconnect to the same socket without having to wait until TIME_WAIT
> state is over.
>
>
>

-- 
Alberto García Illera

GPG Public Key <https://goo.gl/yshdwh>

Archive administrator: postmaster@lists.cynapses.org