linux-sctp.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Xin Long <lucien.xin@gmail.com>
To: minyard@acm.org
Cc: Vlad Yasevich <vyasevich@gmail.com>,
	Neil Horman <nhorman@tuxdriver.com>,
	Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>,
	linux-sctp@vger.kernel.org, LKML <linux-kernel@vger.kernel.org>
Subject: Re: Strange problem with SCTP+IPv6
Date: Mon, 22 Jun 2020 11:52:36 +0000	[thread overview]
Message-ID: <CADvbK_d9mV9rBg7oLC+9u4fg3d_5a_g8ukPe83vOAE8ZM3FhHA@mail.gmail.com> (raw)
In-Reply-To: <20200621155604.GA23135@minyard.net>

On Sun, Jun 21, 2020 at 11:56 PM Corey Minyard <minyard@acm.org> wrote:
>
> 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:
The code only set IPV6_V6ONLY on server side, so the client side will
still bind all the local ipv4 addresses (as you didn't call bind() to
bind any specific addresses ). Then after the connection is created,
the client will send HB on the v4 paths to the server. The server
will abort the connection, as it can't support v4.

So you can work around it by either:

  - set IPV6_V6ONLY on client side.

or

  - bind to the specific v6 addresses on the client side.

I don't see RFC said something about this.
So it may not be a good idea to change the current behaviour
to not establish the connection in this case, which may cause regression.

>
>   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-22 11:52 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-21 15:56 Strange problem with SCTP+IPv6 Corey Minyard
2020-06-22 11:52 ` Xin Long [this message]
2020-06-22 12:32   ` Michael Tuexen
2020-06-22 16:57   ` Corey Minyard
2020-06-22 18:01     ` Michael Tuexen
2020-06-22 18:32       ` Marcelo Ricardo Leitner
2020-06-22 18:34         ` Michael Tuexen
2020-06-23 10:13           ` Xin Long
2020-06-23 13:29             ` Corey Minyard
2020-06-23 15:40               ` Xin Long
2020-06-23 16:00                 ` Corey Minyard
2020-06-24  6:58                   ` Xin Long
2020-06-26 16:13             ` David Laight
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-24 20:31             ` Marcelo Ricardo Leitner
2020-06-24 20:34             ` [PATCH net] " Marcelo Ricardo Leitner
2020-06-24 20:53               ` Corey Minyard
2020-06-25 23:12               ` David Miller
2020-06-23 16:17           ` Strange problem with SCTP+IPv6 Corey Minyard
2020-06-23 21:21             ` 'Marcelo Ricardo Leitner'
2020-06-23 21:24               ` Michael Tuexen
2020-06-23 21:31                 ` Marcelo Ricardo Leitner
2020-06-23 21:48                   ` Michael Tuexen
2020-06-24  7:25                     ` Xin Long
2020-06-24  9:18                       ` 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=CADvbK_d9mV9rBg7oLC+9u4fg3d_5a_g8ukPe83vOAE8ZM3FhHA@mail.gmail.com \
    --to=lucien.xin@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sctp@vger.kernel.org \
    --cc=marcelo.leitner@gmail.com \
    --cc=minyard@acm.org \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).