All of lore.kernel.org
 help / color / mirror / Atom feed
From: Corey Minyard <minyard@acm.org>
To: Vlad Yasevich <vyasevich@gmail.com>,
	Neil Horman <nhorman@tuxdriver.com>,
	Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>,
	linux-sctp@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Subject: Strange problem with SCTP+IPv6
Date: Sun, 21 Jun 2020 10:56:04 -0500	[thread overview]
Message-ID: <20200621155604.GA23135@minyard.net> (raw)

I've stumbled upon a strange problem with SCTP and IPv6.  If I create an
sctp listening socket on :: and set the IPV6_V6ONLY socket option on it,
then I make a connection to it using ::1, the connection will drop after
2.5 seconds with an ECONNRESET error.

It only happens on SCTP, it doesn't have the issue if you connect to a
full IPv6 address instead of ::1, and it doesn't happen if you don't
set IPV6_V6ONLY.  I have verified current end of tree kernel.org.
I tried on an ARM system and x86_64.

I haven't dug into the kernel to see if I could find anything yet, but I
thought I would go ahead and report it.  I am attaching a reproducer.
Basically, compile the following code:

  gcc -g -o sctptest -Wall sctptest.c

and run it in one window as a server:

  ./sctptest a

(Pass in any option to be the server) and run the following in another
window as the client:

  ./sctptest

It disconnects after about 2.5 seconds.  If it works, it should just sit
there forever.

-corey


#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <netinet/sctp.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

static int
getaddr(const char *addr, const char *port, bool listen,
	struct addrinfo **rai)
{
    struct addrinfo *ai, hints;

    memset(&hints, 0, sizeof(hints));
    hints.ai_flags = AI_ADDRCONFIG;
    if (listen)
	hints.ai_flags |= AI_PASSIVE;
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_SCTP;
    if (getaddrinfo(addr, port, &hints, &ai)) {
	perror("getaddrinfo");
	return -1;
    }

    *rai = ai;
    return 0;
}

static int
waitread(int s)
{
    char data[1];
    ssize_t rv;

    rv = read(s, data, sizeof(data));
    if (rv == -1) {
	perror("read");
	return -1;
    }
    printf("Read %d bytes\n", (int) rv);
    return 0;
}

static int
do_server(void)
{
    int err, ls, s, optval;
    struct addrinfo *ai;

    printf("Server\n");

    err = getaddr("::", "3023", true, &ai);
    if (err)
	return err;

    ls = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
    if (ls == -1) {
	perror("socket");
	return -1;
    }

    optval = 1;
    if (setsockopt(ls, SOL_SOCKET, SO_REUSEADDR,
		   (void *)&optval, sizeof(optval)) == -1) {
	perror("setsockopt reuseaddr");
	return -1;
    }

    /* Comment this out and it will work. */
    if (setsockopt(ls, IPPROTO_IPV6, IPV6_V6ONLY, &optval,
		   sizeof(optval)) == -1) {
	perror("setsockopt ipv6 only");
	return -1;
    }

    err = bind(ls, ai->ai_addr, ai->ai_addrlen);
    if (err == -1) {
	perror("bind");
	return -1;
    }

    err = listen(ls, 5);
    if (err == -1) {
	perror("listen");
	return -1;
    }

    s = accept(ls, NULL, NULL);
    if (s == -1) {
	perror("accept");
	return -1;
    }

    close(ls);

    err = waitread(s);
    close(s);
    return err;
}

static int
do_client(void)
{
    int err, s;
    struct addrinfo *ai;

    printf("Client\n");

    err = getaddr("::1", "3023", false, &ai);
    if (err)
	return err;

    s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
    if (s == -1) {
	perror("socket");
	return -1;
    }

    err = connect(s, ai->ai_addr, ai->ai_addrlen);
    if (err == -1) {
	perror("connect");
	return -1;
    }

    err = waitread(s);
    close(s);
    return err;
}

int
main(int argc, char *argv[])
{
    int err;

    if (argc > 1)
	err = do_server();
    else
	err = do_client();
    return !!err;
}


WARNING: multiple messages have this Message-ID (diff)
From: Corey Minyard <minyard@acm.org>
To: Vlad Yasevich <vyasevich@gmail.com>,
	Neil Horman <nhorman@tuxdriver.com>,
	Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>,
	linux-sctp@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Subject: Strange problem with SCTP+IPv6
Date: Sun, 21 Jun 2020 15:56:04 +0000	[thread overview]
Message-ID: <20200621155604.GA23135@minyard.net> (raw)

I've stumbled upon a strange problem with SCTP and IPv6.  If I create an
sctp listening socket on :: and set the IPV6_V6ONLY socket option on it,
then I make a connection to it using ::1, the connection will drop after
2.5 seconds with an ECONNRESET error.

It only happens on SCTP, it doesn't have the issue if you connect to a
full IPv6 address instead of ::1, and it doesn't happen if you don't
set IPV6_V6ONLY.  I have verified current end of tree kernel.org.
I tried on an ARM system and x86_64.

I haven't dug into the kernel to see if I could find anything yet, but I
thought I would go ahead and report it.  I am attaching a reproducer.
Basically, compile the following code:

  gcc -g -o sctptest -Wall sctptest.c

and run it in one window as a server:

  ./sctptest a

(Pass in any option to be the server) and run the following in another
window as the client:

  ./sctptest

It disconnects after about 2.5 seconds.  If it works, it should just sit
there forever.

-corey


#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <netinet/sctp.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

static int
getaddr(const char *addr, const char *port, bool listen,
	struct addrinfo **rai)
{
    struct addrinfo *ai, hints;

    memset(&hints, 0, sizeof(hints));
    hints.ai_flags = AI_ADDRCONFIG;
    if (listen)
	hints.ai_flags |= AI_PASSIVE;
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_SCTP;
    if (getaddrinfo(addr, port, &hints, &ai)) {
	perror("getaddrinfo");
	return -1;
    }

    *rai = ai;
    return 0;
}

static int
waitread(int s)
{
    char data[1];
    ssize_t rv;

    rv = read(s, data, sizeof(data));
    if (rv = -1) {
	perror("read");
	return -1;
    }
    printf("Read %d bytes\n", (int) rv);
    return 0;
}

static int
do_server(void)
{
    int err, ls, s, optval;
    struct addrinfo *ai;

    printf("Server\n");

    err = getaddr("::", "3023", true, &ai);
    if (err)
	return err;

    ls = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
    if (ls = -1) {
	perror("socket");
	return -1;
    }

    optval = 1;
    if (setsockopt(ls, SOL_SOCKET, SO_REUSEADDR,
		   (void *)&optval, sizeof(optval)) = -1) {
	perror("setsockopt reuseaddr");
	return -1;
    }

    /* Comment this out and it will work. */
    if (setsockopt(ls, IPPROTO_IPV6, IPV6_V6ONLY, &optval,
		   sizeof(optval)) = -1) {
	perror("setsockopt ipv6 only");
	return -1;
    }

    err = bind(ls, ai->ai_addr, ai->ai_addrlen);
    if (err = -1) {
	perror("bind");
	return -1;
    }

    err = listen(ls, 5);
    if (err = -1) {
	perror("listen");
	return -1;
    }

    s = accept(ls, NULL, NULL);
    if (s = -1) {
	perror("accept");
	return -1;
    }

    close(ls);

    err = waitread(s);
    close(s);
    return err;
}

static int
do_client(void)
{
    int err, s;
    struct addrinfo *ai;

    printf("Client\n");

    err = getaddr("::1", "3023", false, &ai);
    if (err)
	return err;

    s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
    if (s = -1) {
	perror("socket");
	return -1;
    }

    err = connect(s, ai->ai_addr, ai->ai_addrlen);
    if (err = -1) {
	perror("connect");
	return -1;
    }

    err = waitread(s);
    close(s);
    return err;
}

int
main(int argc, char *argv[])
{
    int err;

    if (argc > 1)
	err = do_server();
    else
	err = do_client();
    return !!err;
}

             reply	other threads:[~2020-06-21 15:56 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-21 15:56 Corey Minyard [this message]
2020-06-21 15:56 ` Strange problem with SCTP+IPv6 Corey Minyard
2020-06-22 11:52 ` Xin Long
2020-06-22 12:01   ` Xin Long
2020-06-22 12:32   ` Michael Tuexen
2020-06-22 12:32     ` Michael Tuexen
2020-06-22 16:57   ` Corey Minyard
2020-06-22 16:57     ` Corey Minyard
2020-06-22 18:01     ` Michael Tuexen
2020-06-22 18:01       ` Michael Tuexen
2020-06-22 18:32       ` Marcelo Ricardo Leitner
2020-06-22 18:32         ` Marcelo Ricardo Leitner
2020-06-22 18:34         ` Michael Tuexen
2020-06-22 18:34           ` Michael Tuexen
2020-06-23 10:13           ` Xin Long
2020-06-23 10:13             ` Xin Long
2020-06-23 13:29             ` Corey Minyard
2020-06-23 13:29               ` Corey Minyard
2020-06-23 15:40               ` Xin Long
2020-06-23 15:40                 ` Xin Long
2020-06-23 16:00                 ` Corey Minyard
2020-06-23 16:00                   ` Corey Minyard
2020-06-24  6:58                   ` Xin Long
2020-06-24  6:58                     ` Xin Long
2020-06-26 16:13             ` David Laight
2020-06-26 16:13               ` David Laight
2020-06-26 16:27               ` Michael Tuexen
2020-06-26 16:27                 ` Michael Tuexen
2020-06-23 13:17         ` David Laight
2020-06-23 16:04           ` [PATCH] sctp: Don't advertise IPv4 addresses if ipv6only is set on the socket minyard
2020-06-23 16:04             ` minyard
2020-06-24 20:31             ` Marcelo Ricardo Leitner
2020-06-24 20:31               ` Marcelo Ricardo Leitner
2020-06-24 20:34             ` [PATCH net] " Marcelo Ricardo Leitner
2020-06-24 20:34               ` Marcelo Ricardo Leitner
2020-06-24 20:53               ` Corey Minyard
2020-06-24 20:53                 ` Corey Minyard
2020-06-25 23:12               ` David Miller
2020-06-25 23:12                 ` David Miller
2020-06-23 16:17           ` Strange problem with SCTP+IPv6 Corey Minyard
2020-06-23 16:17             ` Corey Minyard
2020-06-23 21:21             ` 'Marcelo Ricardo Leitner'
2020-06-23 21:21               ` 'Marcelo Ricardo Leitner'
2020-06-23 21:24               ` Michael Tuexen
2020-06-23 21:24                 ` Michael Tuexen
2020-06-23 21:31                 ` Marcelo Ricardo Leitner
2020-06-23 21:31                   ` Marcelo Ricardo Leitner
2020-06-23 21:48                   ` Michael Tuexen
2020-06-23 21:48                     ` Michael Tuexen
2020-06-24  7:25                     ` Xin Long
2020-06-24  7:25                       ` Xin Long
2020-06-24  9:18                       ` Michael Tuexen
2020-06-24  9:18                         ` Michael Tuexen
2020-06-23 17:09           ` Michael Tuexen
2020-06-23 17:09             ` Michael Tuexen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200621155604.GA23135@minyard.net \
    --to=minyard@acm.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sctp@vger.kernel.org \
    --cc=marcelo.leitner@gmail.com \
    --cc=nhorman@tuxdriver.com \
    --cc=vyasevich@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.