Strange problem with SCTP+IPv6
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 #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; }
Re: Strange problem with SCTP+IPv6
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. > > 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; > } >
Re: Strange problem with SCTP+IPv6
> 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_soc
Re: Strange problem with SCTP+IPv6
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. 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 ar
Re: Strange problem with SCTP+IPv6
> 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,
Re: Strange problem with SCTP+IPv6
On Mon, Jun 22, 2020 at 08:01:24PM +0200, Michael Tuexen wrote: > > 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? It looks like a bug to me. Testing with this test app here, I can see the INIT_ACK being sent with a bunch of ipv4 addresses in it and that's unexpected for a v6only socket. As is, it's the server saying "I'm available at these other addresses too, but not." Thanks, Marcelo > > 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"); > >>>
Re: Strange problem with SCTP+IPv6
> On 22. Jun 2020, at 20:32, Marcelo Ricardo Leitner > wrote: > > On Mon, Jun 22, 2020 at 08:01:24PM +0200, Michael Tuexen wrote: >>> 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? > > It looks like a bug to me. Testing with this test app here, I can see > the INIT_ACK being sent with a bunch of ipv4 addresses in it and > that's unexpected for a v6only socket. As is, it's the server saying > "I'm available at these other addresses too, but not." I agree. Best regards Michael > > Thanks, > Marcelo > >> >> 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,
Re: Strange problem with SCTP+IPv6
On Tue, Jun 23, 2020 at 11:17:56AM -0500, Corey Minyard wrote: > On Tue, Jun 23, 2020 at 01:17:28PM +, David Laight wrote: > > From: Marcelo Ricardo Leitner > > > Sent: 22 June 2020 19:33 > > > On Mon, Jun 22, 2020 at 08:01:24PM +0200, Michael Tuexen wrote: > > > > > 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? > > > > > > It looks like a bug to me. Testing with this test app here, I can see > > > the INIT_ACK being sent with a bunch of ipv4 addresses in it and > > > that's unexpected for a v6only socket. As is, it's the server saying > > > "I'm available at these other addresses too, but not." > > > > Does it even make sense to mix IPv4 and IPv6 addresses on the same > > connection? > > I don't remember ever seeing both types of address in a message, > > but may not have looked. > > That's an interesting question. Do the RFCs say anything? I would > assume it was ok unless ipv6only was set. > > > > > I also wonder whether the connection should be dropped for an error > > response on a path that has never been validated. > > That actually bothered me a bit more. Shouldn't it stay up if any path > is up? That's kind of the whole point of multihoming. Michael explained it on the other email. What he described is what I observed in my tests. > > > > > OTOH the whole 'multi-homing' part of SCTP sucks. > > I don't think so. > > > The IP addresses a server needs to bind to depend on where the > > incoming connection will come from. > > A local connection may be able to use a 192.168.x.x address > > but a remote connection must not - as it may be defined locally > > at the remote system. > > But both connections can come into the public (routable) address. > > We have to tell customers to explicitly configure the local IP > > addresses - which means the application has to know what they are. > > Fortunately these apps are pretty static - usually M3UA. > > Umm, no, If you have a private address, it better be behind a firewall, > and the firewall should handle rewriting the packet to fix the addresses. > > It doesn't appear that Linux netfilter does this. There is a TODO in > the code for this. But that's how it *should* work. Right, we don't support SCTP aware NAT [1]. 1.https://tools.ietf.org/html/draft-stewart-behave-sctpnat-04 Marcelo > > -corey > > > > > David > > > > - > > Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 > > 1PT, UK > > Registration No: 1397386 (Wales) > >
Re: Strange problem with SCTP+IPv6
> On 23. Jun 2020, at 23:21, Marcelo Ricardo Leitner > wrote: > > On Tue, Jun 23, 2020 at 11:17:56AM -0500, Corey Minyard wrote: >> On Tue, Jun 23, 2020 at 01:17:28PM +, David Laight wrote: >>> From: Marcelo Ricardo Leitner Sent: 22 June 2020 19:33 On Mon, Jun 22, 2020 at 08:01:24PM +0200, Michael Tuexen wrote: >> 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? It looks like a bug to me. Testing with this test app here, I can see the INIT_ACK being sent with a bunch of ipv4 addresses in it and that's unexpected for a v6only socket. As is, it's the server saying "I'm available at these other addresses too, but not." >>> >>> Does it even make sense to mix IPv4 and IPv6 addresses on the same >>> connection? >>> I don't remember ever seeing both types of address in a message, >>> but may not have looked. >> >> That's an interesting question. Do the RFCs say anything? I would >> assume it was ok unless ipv6only was set. >> >>> >>> I also wonder whether the connection should be dropped for an error >>> response on a path that has never been validated. >> >> That actually bothered me a bit more. Shouldn't it stay up if any path >> is up? That's kind of the whole point of multihoming. > > Michael explained it on the other email. What he described is what I > observed in my tests. > >> >>> >>> OTOH the whole 'multi-homing' part of SCTP sucks. >> >> I don't think so. >> >>> The IP addresses a server needs to bind to depend on where the >>> incoming connection will come from. >>> A local connection may be able to use a 192.168.x.x address >>> but a remote connection must not - as it may be defined locally >>> at the remote system. >>> But both connections can come into the public (routable) address. >>> We have to tell customers to explicitly configure the local IP >>> addresses - which means the application has to know what they are. >>> Fortunately these apps are pretty static - usually M3UA. >> >> Umm, no, If you have a private address, it better be behind a firewall, >> and the firewall should handle rewriting the packet to fix the addresses. >> >> It doesn't appear that Linux netfilter does this. There is a TODO in >> the code for this. But that's how it *should* work. > > Right, we don't support SCTP aware NAT [1]. > > 1.https://tools.ietf.org/html/draft-stewart-behave-sctpnat-04 The current version is: https://tools.ietf.org/html/draft-ietf-tsvwg-natsupp-16 Another possibility for NAT traversal is UDP encapsulation... Best regards Michael > > Marcelo > >> >> -corey >> >>> >>> David >>> >>> - >>> Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 >>> 1PT, UK >>> Registration No: 1397386 (Wales) >>>
Re: Strange problem with SCTP+IPv6
On Tue, Jun 23, 2020 at 11:24:59PM +0200, Michael Tuexen wrote: > > On 23. Jun 2020, at 23:21, Marcelo Ricardo Leitner > > wrote: > > > > On Tue, Jun 23, 2020 at 11:17:56AM -0500, Corey Minyard wrote: > >> On Tue, Jun 23, 2020 at 01:17:28PM +, David Laight wrote: > >>> From: Marcelo Ricardo Leitner > Sent: 22 June 2020 19:33 > On Mon, Jun 22, 2020 at 08:01:24PM +0200, Michael Tuexen wrote: > >> 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? > > It looks like a bug to me. Testing with this test app here, I can see > the INIT_ACK being sent with a bunch of ipv4 addresses in it and > that's unexpected for a v6only socket. As is, it's the server saying > "I'm available at these other addresses too, but not." > >>> > >>> Does it even make sense to mix IPv4 and IPv6 addresses on the same > >>> connection? > >>> I don't remember ever seeing both types of address in a message, > >>> but may not have looked. > >> > >> That's an interesting question. Do the RFCs say anything? I would > >> assume it was ok unless ipv6only was set. > >> > >>> > >>> I also wonder whether the connection should be dropped for an error > >>> response on a path that has never been validated. > >> > >> That actually bothered me a bit more. Shouldn't it stay up if any path > >> is up? That's kind of the whole point of multihoming. > > > > Michael explained it on the other email. What he described is what I > > observed in my tests. > > > >> > >>> > >>> OTOH the whole 'multi-homing' part of SCTP sucks. > >> > >> I don't think so. > >> > >>> The IP addresses a server needs to bind to depend on where the > >>> incoming connection will come from. > >>> A local connection may be able to use a 192.168.x.x address > >>> but a remote connection must not - as it may be defined locally > >>> at the remote system. > >>> But both connections can come into the public (routable) address. > >>> We have to tell customers to explicitly configure the local IP > >>> addresses - which means the application has to know what they are. > >>> Fortunately these apps are pretty static - usually M3UA. > >> > >> Umm, no, If you have a private address, it better be behind a firewall, > >> and the firewall should handle rewriting the packet to fix the addresses. > >> > >> It doesn't appear that Linux netfilter does this. There is a TODO in > >> the code for this. But that's how it *should* work. > > > > Right, we don't support SCTP aware NAT [1]. > > > > 1.https://tools.ietf.org/html/draft-stewart-behave-sctpnat-04 > The current version is: > https://tools.ietf.org/html/draft-ietf-tsvwg-natsupp-16 Thanks! > > Another possibility for NAT traversal is UDP encapsulation... Also not supported.. :-] Best regards, Marcelo > > Best regards > Michael > > > > Marcelo > > > >> > >> -corey >
Re: Strange problem with SCTP+IPv6
> On 23. Jun 2020, at 23:31, Marcelo Ricardo Leitner > wrote: > > On Tue, Jun 23, 2020 at 11:24:59PM +0200, Michael Tuexen wrote: >>> On 23. Jun 2020, at 23:21, Marcelo Ricardo Leitner >>> wrote: >>> >>> On Tue, Jun 23, 2020 at 11:17:56AM -0500, Corey Minyard wrote: On Tue, Jun 23, 2020 at 01:17:28PM +, David Laight wrote: > From: Marcelo Ricardo Leitner >> Sent: 22 June 2020 19:33 >> On Mon, Jun 22, 2020 at 08:01:24PM +0200, Michael Tuexen wrote: 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? >> >> It looks like a bug to me. Testing with this test app here, I can see >> the INIT_ACK being sent with a bunch of ipv4 addresses in it and >> that's unexpected for a v6only socket. As is, it's the server saying >> "I'm available at these other addresses too, but not." > > Does it even make sense to mix IPv4 and IPv6 addresses on the same > connection? > I don't remember ever seeing both types of address in a message, > but may not have looked. That's an interesting question. Do the RFCs say anything? I would assume it was ok unless ipv6only was set. > > I also wonder whether the connection should be dropped for an error > response on a path that has never been validated. That actually bothered me a bit more. Shouldn't it stay up if any path is up? That's kind of the whole point of multihoming. >>> >>> Michael explained it on the other email. What he described is what I >>> observed in my tests. >>> > > OTOH the whole 'multi-homing' part of SCTP sucks. I don't think so. > The IP addresses a server needs to bind to depend on where the > incoming connection will come from. > A local connection may be able to use a 192.168.x.x address > but a remote connection must not - as it may be defined locally > at the remote system. > But both connections can come into the public (routable) address. > We have to tell customers to explicitly configure the local IP > addresses - which means the application has to know what they are. > Fortunately these apps are pretty static - usually M3UA. Umm, no, If you have a private address, it better be behind a firewall, and the firewall should handle rewriting the packet to fix the addresses. It doesn't appear that Linux netfilter does this. There is a TODO in the code for this. But that's how it *should* work. >>> >>> Right, we don't support SCTP aware NAT [1]. >>> >>> 1.https://tools.ietf.org/html/draft-stewart-behave-sctpnat-04 >> The current version is: >> https://tools.ietf.org/html/draft-ietf-tsvwg-natsupp-16 > > Thanks! > >> >> Another possibility for NAT traversal is UDP encapsulation... > > Also not supported.. :-] But maybe so
Re: Strange problem with SCTP+IPv6
On Wed, Jun 24, 2020 at 12:00 AM Corey Minyard wrote: > > On Tue, Jun 23, 2020 at 11:40:21PM +0800, Xin Long wrote: > > On Tue, Jun 23, 2020 at 9:29 PM Corey Minyard wrote: > > > > > > On Tue, Jun 23, 2020 at 06:13:30PM +0800, Xin Long wrote: > > > > On Tue, Jun 23, 2020 at 2:34 AM Michael Tuexen > > > > wrote: > > > > > > > > > > > On 22. Jun 2020, at 20:32, Marcelo Ricardo Leitner > > > > > > wrote: > > > > > > > > > > > > On Mon, Jun 22, 2020 at 08:01:24PM +0200, Michael Tuexen wrote: > > > > > >>> 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? > > > > > > > > > > > > It looks like a bug to me. Testing with this test app here, I can > > > > > > see > > > > > > the INIT_ACK being sent with a bunch of ipv4 addresses in it and > > > > > > that's unexpected for a v6only socket. As is, it's the server saying > > > > > > "I'm available at these other addresses too, but not." > > > > > I agree. > > > > Then we need a fix in sctp_bind_addrs_to_raw(): > > > > > > > > @@ -238,6 +240,9 @@ union sctp_params sctp_bind_addrs_to_raw(const > > > > struct sctp_bind_addr *bp, > > > > addrparms = retval; > > > > > > > > list_for_each_entry(addr, &bp->address_list, list) { > > > > + if ((PF_INET6 == sk->sk_family) && inet_v6_ipv6only(sk) > > > > && > > > > + (AF_INET == addr->a.sa.sa_family)) > > > > + continue; > > > > > > This does not compile in the latest mainline. sk is not defined. > > > Also, if you could send a normal git patch, that would be easier to > > > manage. > > sorry, that was just the code to show the idea. > > > > For the compilable one, pls see: > > https://paste.centos.org/view/49f5ff5a > > The kernel community runs on patches. It's hard to talk about changes > if you put things in pastbin type of stuff. Please send full complete > patches in emails. I will do that in a moment. I thought you wanted a temporary patch to run your test. The final patch still needs some change, like drop the *bp param even from sctp_make_init(). > > Anyway, are use sure every bp passed into sctp_bind_addrs_to_raw() > is &asoc->base.bind_addr? It's passed in to sctp_make_init() and the > passed to sctp_bind_addrs_to_raw(). If this is the case, you can remove > it from the parameters of sctp_make_init(). But I suspect it's passed > in for a reason. This is not difficult to track. path 1: sctp_sf_do_5_2_6_stale()/sctp_sf_do_prm_asoc()/ sctp_sf_t1_init_timer_expire() -> sctp_make_init() -> sctp_bin
Re: Strange problem with SCTP+IPv6
On Wed, Jun 24, 2020 at 5:48 AM Michael Tuexen wrote: > > > On 23. Jun 2020, at 23:31, Marcelo Ricardo Leitner > > wrote: > > > > On Tue, Jun 23, 2020 at 11:24:59PM +0200, Michael Tuexen wrote: > >>> On 23. Jun 2020, at 23:21, Marcelo Ricardo Leitner > >>> wrote: > >>> > >>> On Tue, Jun 23, 2020 at 11:17:56AM -0500, Corey Minyard wrote: > On Tue, Jun 23, 2020 at 01:17:28PM +, David Laight wrote: > > From: Marcelo Ricardo Leitner > >> Sent: 22 June 2020 19:33 > >> On Mon, Jun 22, 2020 at 08:01:24PM +0200, Michael Tuexen wrote: > 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? > >> > >> It looks like a bug to me. Testing with this test app here, I can see > >> the INIT_ACK being sent with a bunch of ipv4 addresses in it and > >> that's unexpected for a v6only socket. As is, it's the server saying > >> "I'm available at these other addresses too, but not." > > > > Does it even make sense to mix IPv4 and IPv6 addresses on the same > > connection? > > I don't remember ever seeing both types of address in a message, > > but may not have looked. > > That's an interesting question. Do the RFCs say anything? I would > assume it was ok unless ipv6only was set. > > > > > I also wonder whether the connection should be dropped for an error > > response on a path that has never been validated. > > That actually bothered me a bit more. Shouldn't it stay up if any path > is up? That's kind of the whole point of multihoming. > >>> > >>> Michael explained it on the other email. What he described is what I > >>> observed in my tests. > >>> > > > > > OTOH the whole 'multi-homing' part of SCTP sucks. > > I don't think so. > > > The IP addresses a server needs to bind to depend on where the > > incoming connection will come from. > > A local connection may be able to use a 192.168.x.x address > > but a remote connection must not - as it may be defined locally > > at the remote system. > > But both connections can come into the public (routable) address. > > We have to tell customers to explicitly configure the local IP > > addresses - which means the application has to know what they are. > > Fortunately these apps are pretty static - usually M3UA. > > Umm, no, If you have a private address, it better be behind a firewall, > and the firewall should handle rewriting the packet to fix the addresses. > > It doesn't appear that Linux netfilter does this. There is a TODO in > the code for this. But that's how it *should* work. > >>> > >>> Right, we don't support SCTP aw
Re: Strange problem with SCTP+IPv6
> On 24. Jun 2020, at 09:25, Xin Long wrote: > > On Wed, Jun 24, 2020 at 5:48 AM Michael Tuexen > wrote: >> >>> On 23. Jun 2020, at 23:31, Marcelo Ricardo Leitner >>> wrote: >>> >>> On Tue, Jun 23, 2020 at 11:24:59PM +0200, Michael Tuexen wrote: > On 23. Jun 2020, at 23:21, Marcelo Ricardo Leitner > wrote: > > On Tue, Jun 23, 2020 at 11:17:56AM -0500, Corey Minyard wrote: >> On Tue, Jun 23, 2020 at 01:17:28PM +, David Laight wrote: >>> From: Marcelo Ricardo Leitner Sent: 22 June 2020 19:33 On Mon, Jun 22, 2020 at 08:01:24PM +0200, Michael Tuexen wrote: >> 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? It looks like a bug to me. Testing with this test app here, I can see the INIT_ACK being sent with a bunch of ipv4 addresses in it and that's unexpected for a v6only socket. As is, it's the server saying "I'm available at these other addresses too, but not." >>> >>> Does it even make sense to mix IPv4 and IPv6 addresses on the same >>> connection? >>> I don't remember ever seeing both types of address in a message, >>> but may not have looked. >> >> That's an interesting question. Do the RFCs say anything? I would >> assume it was ok unless ipv6only was set. >> >>> >>> I also wonder whether the connection should be dropped for an error >>> response on a path that has never been validated. >> >> That actually bothered me a bit more. Shouldn't it stay up if any path >> is up? That's kind of the whole point of multihoming. > > Michael explained it on the other email. What he described is what I > observed in my tests. > >> >>> >>> OTOH the whole 'multi-homing' part of SCTP sucks. >> >> I don't think so. >> >>> The IP addresses a server needs to bind to depend on where the >>> incoming connection will come from. >>> A local connection may be able to use a 192.168.x.x address >>> but a remote connection must not - as it may be defined locally >>> at the remote system. >>> But both connections can come into the public (routable) address. >>> We have to tell customers to explicitly configure the local IP >>> addresses - which means the application has to know what they are. >>> Fortunately these apps are pretty static - usually M3UA. >> >> Umm, no, If you have a private address, it better be behind a firewall, >> and the firewall should handle rewriting the packet to fix the addresses. >> >> It doesn't appear that Linux netfilter does this. There is a TODO in >> the code for th
RE: Strange problem with SCTP+IPv6
From: Xin Long > Sent: 23 June 2020 11:14 > > > It looks like a bug to me. Testing with this test app here, I can see > > > the INIT_ACK being sent with a bunch of ipv4 addresses in it and > > > that's unexpected for a v6only socket. As is, it's the server saying > > > "I'm available at these other addresses too, but not." > > I agree. > Then we need a fix in sctp_bind_addrs_to_raw(): > > @@ -238,6 +240,9 @@ union sctp_params sctp_bind_addrs_to_raw(const > struct sctp_bind_addr *bp, > addrparms = retval; > > list_for_each_entry(addr, &bp->address_list, list) { > + if ((PF_INET6 == sk->sk_family) && inet_v6_ipv6only(sk) && > + (AF_INET == addr->a.sa.sa_family)) > + continue; > af = sctp_get_af_specific(addr->a.v4.sin_family); > len = af->to_addr_param(&addr->a, &rawaddr); > memcpy(addrparms.v, &rawaddr, len); Thought. Does it make any sense to offer addresses in the INIT_ACK that don't have routes to those proposed in the received INIT? 'routes' probably isn't exactly the right word. You probably only want the local address that will be used as the source address for the probes. Or, at least, sources addresses that could be used for the probes. So if the INIT only contains IPv6 addresses should the INIT_ACK ever contain IPv4 ones. David. - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)
Re: Strange problem with SCTP+IPv6
> On 26. Jun 2020, at 18:13, David Laight wrote: > > From: Xin Long >> Sent: 23 June 2020 11:14 It looks like a bug to me. Testing with this test app here, I can see the INIT_ACK being sent with a bunch of ipv4 addresses in it and that's unexpected for a v6only socket. As is, it's the server saying "I'm available at these other addresses too, but not." >>> I agree. >> Then we need a fix in sctp_bind_addrs_to_raw(): >> >> @@ -238,6 +240,9 @@ union sctp_params sctp_bind_addrs_to_raw(const >> struct sctp_bind_addr *bp, >>addrparms = retval; >> >>list_for_each_entry(addr, &bp->address_list, list) { >> + if ((PF_INET6 == sk->sk_family) && inet_v6_ipv6only(sk) && >> + (AF_INET == addr->a.sa.sa_family)) >> + continue; >>af = sctp_get_af_specific(addr->a.v4.sin_family); >>len = af->to_addr_param(&addr->a, &rawaddr); >>memcpy(addrparms.v, &rawaddr, len); > > Thought. > > Does it make any sense to offer addresses in the INIT_ACK that don't > have routes to those proposed in the received INIT? > > 'routes' probably isn't exactly the right word. > You probably only want the local address that will be used > as the source address for the probes. > Or, at least, sources addresses that could be used for the probes. > > So if the INIT only contains IPv6 addresses should the INIT_ACK > ever contain IPv4 ones. The client (if it not using an IPv6 socket having IPv6 only enabled) could add an IPv4 address during the lifetime of the association by using the address reconfiguration extension. What could be done is to not send IPv4 addresses if the INIT contains a Supported Address Types parameter indicating IPv6, but not IPv4 support. As a client you might want to send this parameter, when the IPv6 socket has enabled the IPV6_ONLY socket option. Also if the client uses an IPv4 socket, it can indicate in the Supported Address Parameter that it only support IPv4, and the server does not need to list IPv6 addresses. Best regards Michael > > David. > > - > Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 > 1PT, UK > Registration No: 1397386 (Wales)
Re: Strange problem with SCTP+IPv6
On Tue, Jun 23, 2020 at 2:34 AM Michael Tuexen wrote: > > > On 22. Jun 2020, at 20:32, Marcelo Ricardo Leitner > > wrote: > > > > On Mon, Jun 22, 2020 at 08:01:24PM +0200, Michael Tuexen wrote: > >>> 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? > > > > It looks like a bug to me. Testing with this test app here, I can see > > the INIT_ACK being sent with a bunch of ipv4 addresses in it and > > that's unexpected for a v6only socket. As is, it's the server saying > > "I'm available at these other addresses too, but not." > I agree. Then we need a fix in sctp_bind_addrs_to_raw(): @@ -238,6 +240,9 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp, addrparms = retval; list_for_each_entry(addr, &bp->address_list, list) { + if ((PF_INET6 == sk->sk_family) && inet_v6_ipv6only(sk) && + (AF_INET == addr->a.sa.sa_family)) + continue; af = sctp_get_af_specific(addr->a.v4.sin_family); len = af->to_addr_param(&addr->a, &rawaddr); memcpy(addrparms.v, &rawaddr, len); > > Best regards > Michael > > > > Thanks, > > Marcelo > > > >> > >> 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 =
RE: Strange problem with SCTP+IPv6
From: Marcelo Ricardo Leitner > Sent: 22 June 2020 19:33 > On Mon, Jun 22, 2020 at 08:01:24PM +0200, Michael Tuexen wrote: > > > 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? > > It looks like a bug to me. Testing with this test app here, I can see > the INIT_ACK being sent with a bunch of ipv4 addresses in it and > that's unexpected for a v6only socket. As is, it's the server saying > "I'm available at these other addresses too, but not." Does it even make sense to mix IPv4 and IPv6 addresses on the same connection? I don't remember ever seeing both types of address in a message, but may not have looked. I also wonder whether the connection should be dropped for an error response on a path that has never been validated. OTOH the whole 'multi-homing' part of SCTP sucks. The IP addresses a server needs to bind to depend on where the incoming connection will come from. A local connection may be able to use a 192.168.x.x address but a remote connection must not - as it may be defined locally at the remote system. But both connections can come into the public (routable) address. We have to tell customers to explicitly configure the local IP addresses - which means the application has to know what they are. Fortunately these apps are pretty static - usually M3UA. David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)
Re: Strange problem with SCTP+IPv6
On Tue, Jun 23, 2020 at 06:13:30PM +0800, Xin Long wrote: > On Tue, Jun 23, 2020 at 2:34 AM Michael Tuexen > wrote: > > > > > On 22. Jun 2020, at 20:32, Marcelo Ricardo Leitner > > > wrote: > > > > > > On Mon, Jun 22, 2020 at 08:01:24PM +0200, Michael Tuexen wrote: > > >>> 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? > > > > > > It looks like a bug to me. Testing with this test app here, I can see > > > the INIT_ACK being sent with a bunch of ipv4 addresses in it and > > > that's unexpected for a v6only socket. As is, it's the server saying > > > "I'm available at these other addresses too, but not." > > I agree. > Then we need a fix in sctp_bind_addrs_to_raw(): > > @@ -238,6 +240,9 @@ union sctp_params sctp_bind_addrs_to_raw(const > struct sctp_bind_addr *bp, > addrparms = retval; > > list_for_each_entry(addr, &bp->address_list, list) { > + if ((PF_INET6 == sk->sk_family) && inet_v6_ipv6only(sk) && > + (AF_INET == addr->a.sa.sa_family)) > + continue; This does not compile in the latest mainline. sk is not defined. Also, if you could send a normal git patch, that would be easier to manage. Thanks, -corey > af = sctp_get_af_specific(addr->a.v4.sin_family); > len = af->to_addr_param(&addr->a, &rawaddr); > memcpy(addrparms.v, &rawaddr, len); > > > > > Best regards > > Michael > > > > > > Thanks, > > > Marcelo > > > > > >> > > >> 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 =
Re: Strange problem with SCTP+IPv6
On Tue, Jun 23, 2020 at 9:29 PM Corey Minyard wrote: > > On Tue, Jun 23, 2020 at 06:13:30PM +0800, Xin Long wrote: > > On Tue, Jun 23, 2020 at 2:34 AM Michael Tuexen > > wrote: > > > > > > > On 22. Jun 2020, at 20:32, Marcelo Ricardo Leitner > > > > wrote: > > > > > > > > On Mon, Jun 22, 2020 at 08:01:24PM +0200, Michael Tuexen wrote: > > > >>> 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? > > > > > > > > It looks like a bug to me. Testing with this test app here, I can see > > > > the INIT_ACK being sent with a bunch of ipv4 addresses in it and > > > > that's unexpected for a v6only socket. As is, it's the server saying > > > > "I'm available at these other addresses too, but not." > > > I agree. > > Then we need a fix in sctp_bind_addrs_to_raw(): > > > > @@ -238,6 +240,9 @@ union sctp_params sctp_bind_addrs_to_raw(const > > struct sctp_bind_addr *bp, > > addrparms = retval; > > > > list_for_each_entry(addr, &bp->address_list, list) { > > + if ((PF_INET6 == sk->sk_family) && inet_v6_ipv6only(sk) && > > + (AF_INET == addr->a.sa.sa_family)) > > + continue; > > This does not compile in the latest mainline. sk is not defined. > Also, if you could send a normal git patch, that would be easier to > manage. sorry, that was just the code to show the idea. For the compilable one, pls see: https://paste.centos.org/view/49f5ff5a Thanks. > > Thanks, > > -corey > > > af = sctp_get_af_specific(addr->a.v4.sin_family); > > len = af->to_addr_param(&addr->a, &rawaddr); > > memcpy(addrparms.v, &rawaddr, len); > > > > > > > > Best regards > > > Michael > > > > > > > > Thanks, > > > > Marcelo > > > > > > > >> > > > >> 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) > > > > { > > >
Re: Strange problem with SCTP+IPv6
On Tue, Jun 23, 2020 at 11:40:21PM +0800, Xin Long wrote: > On Tue, Jun 23, 2020 at 9:29 PM Corey Minyard wrote: > > > > On Tue, Jun 23, 2020 at 06:13:30PM +0800, Xin Long wrote: > > > On Tue, Jun 23, 2020 at 2:34 AM Michael Tuexen > > > wrote: > > > > > > > > > On 22. Jun 2020, at 20:32, Marcelo Ricardo Leitner > > > > > wrote: > > > > > > > > > > On Mon, Jun 22, 2020 at 08:01:24PM +0200, Michael Tuexen wrote: > > > > >>> 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? > > > > > > > > > > It looks like a bug to me. Testing with this test app here, I can see > > > > > the INIT_ACK being sent with a bunch of ipv4 addresses in it and > > > > > that's unexpected for a v6only socket. As is, it's the server saying > > > > > "I'm available at these other addresses too, but not." > > > > I agree. > > > Then we need a fix in sctp_bind_addrs_to_raw(): > > > > > > @@ -238,6 +240,9 @@ union sctp_params sctp_bind_addrs_to_raw(const > > > struct sctp_bind_addr *bp, > > > addrparms = retval; > > > > > > list_for_each_entry(addr, &bp->address_list, list) { > > > + if ((PF_INET6 == sk->sk_family) && inet_v6_ipv6only(sk) && > > > + (AF_INET == addr->a.sa.sa_family)) > > > + continue; > > > > This does not compile in the latest mainline. sk is not defined. > > Also, if you could send a normal git patch, that would be easier to > > manage. > sorry, that was just the code to show the idea. > > For the compilable one, pls see: > https://paste.centos.org/view/49f5ff5a The kernel community runs on patches. It's hard to talk about changes if you put things in pastbin type of stuff. Please send full complete patches in emails. I will do that in a moment. Anyway, are use sure every bp passed into sctp_bind_addrs_to_raw() is &asoc->base.bind_addr? It's passed in to sctp_make_init() and the passed to sctp_bind_addrs_to_raw(). If this is the case, you can remove it from the parameters of sctp_make_init(). But I suspect it's passed in for a reason. Anyway, I have a patch I have compiled and tested, I will send that. -corey > > Thanks. > > > > Thanks, > > > > -corey > > > > > af = sctp_get_af_specific(addr->a.v4.sin_family); > > > len = af->to_addr_param(&addr->a, &rawaddr); > > > memcpy(addrparms.v, &rawaddr, len); > > > > > > > > > > > Best regards > > > > Michael > > > > > > > > > > Thanks, > > > > > Marcelo > > > > > > > > > >> > > > > >> Best regards > > > > >> Michael > > > > >>> > > > > >>> Thanks, > > > > >>> > > > > >>> -corey > > > > >>> > > > > > > > > > > > > >
Re: Strange problem with SCTP+IPv6
On Tue, Jun 23, 2020 at 01:17:28PM +, David Laight wrote: > From: Marcelo Ricardo Leitner > > Sent: 22 June 2020 19:33 > > On Mon, Jun 22, 2020 at 08:01:24PM +0200, Michael Tuexen wrote: > > > > 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? > > > > It looks like a bug to me. Testing with this test app here, I can see > > the INIT_ACK being sent with a bunch of ipv4 addresses in it and > > that's unexpected for a v6only socket. As is, it's the server saying > > "I'm available at these other addresses too, but not." > > Does it even make sense to mix IPv4 and IPv6 addresses on the same > connection? > I don't remember ever seeing both types of address in a message, > but may not have looked. That's an interesting question. Do the RFCs say anything? I would assume it was ok unless ipv6only was set. > > I also wonder whether the connection should be dropped for an error > response on a path that has never been validated. That actually bothered me a bit more. Shouldn't it stay up if any path is up? That's kind of the whole point of multihoming. > > OTOH the whole 'multi-homing' part of SCTP sucks. I don't think so. > The IP addresses a server needs to bind to depend on where the > incoming connection will come from. > A local connection may be able to use a 192.168.x.x address > but a remote connection must not - as it may be defined locally > at the remote system. > But both connections can come into the public (routable) address. > We have to tell customers to explicitly configure the local IP > addresses - which means the application has to know what they are. > Fortunately these apps are pretty static - usually M3UA. Umm, no, If you have a private address, it better be behind a firewall, and the firewall should handle rewriting the packet to fix the addresses. It doesn't appear that Linux netfilter does this. There is a TODO in the code for this. But that's how it *should* work. -corey > > David > > - > Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 > 1PT, UK > Registration No: 1397386 (Wales) >
Re: Strange problem with SCTP+IPv6
> On 23. Jun 2020, at 15:17, David Laight wrote: > > From: Marcelo Ricardo Leitner >> Sent: 22 June 2020 19:33 >> On Mon, Jun 22, 2020 at 08:01:24PM +0200, Michael Tuexen wrote: 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? >> >> It looks like a bug to me. Testing with this test app here, I can see >> the INIT_ACK being sent with a bunch of ipv4 addresses in it and >> that's unexpected for a v6only socket. As is, it's the server saying >> "I'm available at these other addresses too, but not." > > Does it even make sense to mix IPv4 and IPv6 addresses on the same > connection? Sure, if you have an IPv6 socket, which has not enabled the IPV6ONLY socket option. > I don't remember ever seeing both types of address in a message, > but may not have looked. > > I also wonder whether the connection should be dropped for an error > response on a path that has never been validated. Assuming that it is not an ERROR chunk which comes back, but an ABORT, this should happen as long as the verification tag is OK. > > OTOH the whole 'multi-homing' part of SCTP sucks. > The IP addresses a server needs to bind to depend on where the > incoming connection will come from. Not sure what this means. The application can bind a wildcard address or a specific subset. However, when an INIT comes in, the INIT-ACK might contain only a subset of there due to scoping. > A local connection may be able to use a 192.168.x.x address > but a remote connection must not - as it may be defined locally > at the remote system. Yepp. Not sure what you can do about it. > But both connections can come into the public (routable) address. > We have to tell customers to explicitly configure the local IP > addresses - which means the application has to know what they are. > Fortunately these apps are pretty static - usually M3UA. Please note that in SIGRTRAN scenarios you normally not have NATs involved as you have usually in setups used at home. Best regards Michael > > David > > - > Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 > 1PT, UK > Registration No: 1397386 (Wales) >