Received: by 2002:a05:6902:102b:0:0:0:0 with SMTP id x11csp2731073ybt; Mon, 22 Jun 2020 05:46:21 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxZZ1kNCLdPuLHRPibbjmod5dmvxNMB11k9MUwnzDxrNs7okujNxmYrC6MsxkMZrcBPsm/k X-Received: by 2002:aa7:ce13:: with SMTP id d19mr17196740edv.355.1592829981583; Mon, 22 Jun 2020 05:46:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1592829981; cv=none; d=google.com; s=arc-20160816; b=PGee/NuB8gURkhFv2TNLoeXbsjcv74jbBQspYEgRrI8WgZogPHYUWUt8J6CR3wzOGL 5KAvCY5nrQadqih2mij6waF6nToAY1GFmo+ZO1Cyzd5L98wSvZngBUYWrraTLhO+SjtI q8phf+/JCjxxej/SSzry1smcALZuWn0lnBYm3sUtxkUFuY6DmfKLcE/ORl4GjcKua0kt 6N6rujpg8vAiPVYAVdspqb1YJQHTlJQc8am2QCs5oKrp9X4QhSGw40TWuK0oyNDcDqHF 6CdO3WaMGoH0AuQFxLIdFi7mcT/8X2HOiCHuN/4AvxceYQCUi4nxi4wWS5cHW3HGRjGp ltOA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:to:references:message-id :content-transfer-encoding:cc:date:in-reply-to:from:subject :mime-version; bh=mL/OoD8IW5NNkeq2OjSJ4TxJGk29ij1P3kMli23qoZw=; b=xwQYFvVZpekvPy4oLAsllZU9l8K6T9u0v9S1LtZQBcIBxzWJFtGvO/hkGpyAZ1KS7d 4UhvB9afOP4xGZwMf31dKgX+TdbhhCGGI658RUJNIriU8TKW0x3Lm7bdo2EuQQtreaSo AAfOMKU0naB0blTFNh1sininqYXHrq9Mcr0ItljV8dDXN7EQkLEK+ieERQBzaIIGphcN T9MYQ57mWRGuGJt/4WiJWwb+O1jJy5tvhx2CaF2/Q1BilF+GQBb8HlPXOC/ZM4Ca0/O/ 4TaJm1oJU9vM56aeiCYfZ282NkJOwsGR26CqbvOACWMlJFL9TvnGlYZHIxnqKDFNL0b0 aWwg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id ci9si8800684ejb.218.2020.06.22.05.45.59; Mon, 22 Jun 2020 05:46:21 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728283AbgFVMmA (ORCPT + 99 others); Mon, 22 Jun 2020 08:42:00 -0400 Received: from mail-n.franken.de ([193.175.24.27]:41500 "EHLO drew.franken.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728122AbgFVMmA (ORCPT ); Mon, 22 Jun 2020 08:42:00 -0400 X-Greylist: delayed 530 seconds by postgrey-1.27 at vger.kernel.org; Mon, 22 Jun 2020 08:41:59 EDT Received: from mb.fritz.box (ip4d15f5fc.dynamic.kabel-deutschland.de [77.21.245.252]) (Authenticated sender: lurchi) by mail-n.franken.de (Postfix) with ESMTPSA id 44BD27220C6C8; Mon, 22 Jun 2020 14:33:00 +0200 (CEST) Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (Mac OS X Mail 13.4 \(3608.80.23.2.2\)) Subject: Re: Strange problem with SCTP+IPv6 From: Michael Tuexen In-Reply-To: Date: Mon, 22 Jun 2020 14:32:57 +0200 Cc: minyard@acm.org, Vlad Yasevich , Neil Horman , Marcelo Ricardo Leitner , linux-sctp@vger.kernel.org, LKML Content-Transfer-Encoding: 7bit Message-Id: References: <20200621155604.GA23135@minyard.net> To: Xin Long X-Mailer: Apple Mail (2.3608.80.23.2.2) X-Spam-Status: No, score=-2.9 required=5.0 tests=ALL_TRUSTED,BAYES_00 autolearn=disabled version=3.4.1 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on mail-n.franken.de Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org > On 22. Jun 2020, at 14:01, Xin Long wrote: > > On Sun, Jun 21, 2020 at 11:56 PM Corey Minyard 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, Let's focus on the loopback addresses ::1 and 127.0.0.1. So the server will only use ::1. The client will send an INIT from ::1 to ::1 and lists 127.0.0.1 and ::1. That is what I would expect. Is that happening? The server would respond with an INIT-ACK from ::1 to ::1 and would not list any IP addresses. Especially not 127.0.0.1, since it is IPv6 only. After the association has beed established, the client can't send any IPv4 packet to the server, since the server did not announce any. The server can't send any IPv4 packets since it is IPv6 only. This is what I would expect and this scenario should just work. What am I missing? Best regards Michael > 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 >> #include >> #include >> #include >> #include >> #include >> #include >> #include >> #include >> #include >> #include >> >> 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; >> } >>