Received: by 2002:a05:6902:102b:0:0:0:0 with SMTP id x11csp2951894ybt; Mon, 22 Jun 2020 11:04:00 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzJv55zB7vZLMFgMpPdjxlwjeMPF6LlCctk9PiTinSXdb7Zr/C1L0OtP/p4GvBmYxq26NQW X-Received: by 2002:a17:906:4f94:: with SMTP id o20mr16315680eju.113.1592849040551; Mon, 22 Jun 2020 11:04:00 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1592849040; cv=none; d=google.com; s=arc-20160816; b=eAyxLDYjx4tIkFIkzv0hZ23h60wSl3Ix49qZgjZN0dK3gGvcLjrNMqXtVH4I3dm4Qy m4mha5WlPIoOV/V/pXB6U9ZJNkb87YfnvfpYzGKOoCS0Tg8Rnqso4cSiUWcIgwMBrHdn /uv5b/FzKHwz3jZ3XT5nImbQiCugTuRVH/WAZ0whYqfYo7L0HwfaUO6mWYAq5nuGXWmk kmPggx0bqEyfhe+Lcp98YfsM01gVvPJhGzbqtvGMropN7meuU+SnFZiQjtbm18I76wRt dtAVW+QZjmQ14Q9fhNosMGKKtCcbxly0EUpfJ/LTD1N9DJ592TsRHXyIYBwIDziqhM5/ 5PuA== 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=B9JzdmqZLFI03MjSkT3XoRyvNCHNytFl+vFdkfuBhZQ=; b=k/JOVFlDHaVlLxxrP2S8+kzdmM6ppi+dVifNYI7xHRdmDtGt1cxgMwpwLVDPVyM3Qz +Ua6+CiI8y2GFmy2DaY66u26yDWyNzojM7UbPnjaCZR7tIE5rAf6KydSSs8NxzR4K+ct Vz9eQ9b1ppysm9SIdhmYPz2VOfqocCAwdzpFGjcawSMUq71kZUEXsitqpuY5xICzlsfR SwcK4d4dgpGXpTy0ZanzwP+31j7FTMwgJMNTxYdybdETJhAN4ydeN46Z/K/seTbKaqEB J+8cDndyrljVAHegYFpbz/5LpwJbZ40vj7xSRhDnTnYEdQfueu1KnRLPEBlMUS5JENvd nORA== 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 s23si10309602edr.605.2020.06.22.11.03.35; Mon, 22 Jun 2020 11:04:00 -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 S1730210AbgFVSBc (ORCPT + 99 others); Mon, 22 Jun 2020 14:01:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33602 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730046AbgFVSBb (ORCPT ); Mon, 22 Jun 2020 14:01:31 -0400 X-Greylist: delayed 19702 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Mon, 22 Jun 2020 11:01:30 PDT Received: from drew.franken.de (drew.ipv6.franken.de [IPv6:2001:638:a02:a001:20e:cff:fe4a:feaa]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C9DDFC061573; Mon, 22 Jun 2020 11:01:30 -0700 (PDT) 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 3B0057220C6C8; Mon, 22 Jun 2020 20:01:26 +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: <20200622165759.GA3235@minyard.net> Date: Mon, 22 Jun 2020 20:01:24 +0200 Cc: Xin Long , Vlad Yasevich , Neil Horman , Marcelo Ricardo Leitner , linux-sctp@vger.kernel.org, LKML Content-Transfer-Encoding: 7bit Message-Id: <4B68D06C-00F4-42C3-804A-B5531AABCE21@lurchi.franken.de> References: <20200621155604.GA23135@minyard.net> <20200622165759.GA3235@minyard.net> To: minyard@acm.org 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 18:57, Corey Minyard wrote: > > On Mon, Jun 22, 2020 at 08:01:23PM +0800, 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, >> 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. > > Ok, I understand this. It's a little strange, but I see why it works > this way. I don't. I would expect it to work as I described in my email. Could someone explain me how and why it is behaving different from my expectation? Best regards Michael > > Thanks, > > -corey > >> >>> >>> 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; >>> } >>>