1 /*
2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23
24 /*
25 * @test
26 * @bug 8210493
27 * @requires os.family == "linux"
28 * @library /test/lib
29 * @build jdk.test.lib.NetworkConfiguration
30 * PromiscuousIPv6
31 * @run main PromiscuousIPv6
32 * @key randomness
33 */
34
35 import java.nio.ByteBuffer;
36 import java.nio.channels.*;
37 import java.net.*;
38 import static java.net.StandardProtocolFamily.*;
39 import java.util.*;
40 import java.io.IOException;
41 import java.util.stream.Collectors;
42
43 import jdk.test.lib.NetworkConfiguration;
44 import jtreg.SkippedException;
45
46 /*
47 * This test was created as a copy of the Promiscuous test and adapted for
48 * IPv6 node-local and link-local multicast addresses on Linux.
49 */
50 public class PromiscuousIPv6 {
51
52 static final Random rand = new Random();
53
54 static final ProtocolFamily UNSPEC = () -> "UNSPEC";
55
56 /**
57 * Sends a datagram to the given multicast group
58 */
59 static int sendDatagram(NetworkInterface nif,
60 InetAddress group,
61 int port)
62 throws IOException
63 {
64 ProtocolFamily family = (group instanceof Inet6Address) ?
65 StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
66 DatagramChannel dc = DatagramChannel.open(family)
67 .setOption(StandardSocketOptions.IP_MULTICAST_IF, nif);
68 int id = rand.nextInt();
69 byte[] msg = Integer.toString(id).getBytes("UTF-8");
70 ByteBuffer buf = ByteBuffer.wrap(msg);
71 System.out.format("Send message -> group %s (id=0x%x)\n",
72 group.getHostAddress(), id);
73 dc.send(buf, new InetSocketAddress(group, port));
74 dc.close();
75 return id;
76 }
77
78 /**
79 * Wait (with timeout) for datagram. The {@code datagramExpected}
80 * parameter indicates whether a datagram is expected, and if
81 * {@code true} then {@code id} is the identifier in the payload.
82 */
83 static void receiveDatagram(DatagramChannel dc,
84 String name,
85 boolean datagramExpected,
86 int id)
87 throws IOException
88 {
89 System.out.println("Checking if received by " + name);
90
91 Selector sel = Selector.open();
92 dc.configureBlocking(false);
93 dc.register(sel, SelectionKey.OP_READ);
94 ByteBuffer buf = ByteBuffer.allocateDirect(100);
95
96 try {
97 for (;;) {
98 System.out.println("Waiting to receive message");
99 sel.select(5*1000);
136 System.out.println("Message ignored (wrong sender)");
137 }
138
139 sel.selectedKeys().clear();
140 buf.rewind();
141 }
142 } finally {
143 sel.close();
144 }
145 }
146
147 static void test(ProtocolFamily family,
148 NetworkInterface nif,
149 InetAddress group1,
150 InetAddress group2)
151 throws IOException
152 {
153
154 System.out.format("%nTest family=%s%n", family.name());
155
156 DatagramChannel dc1 = (family == UNSPEC) ?
157 DatagramChannel.open() : DatagramChannel.open(family);
158 DatagramChannel dc2 = (family == UNSPEC) ?
159 DatagramChannel.open() : DatagramChannel.open(family);
160
161 try {
162 dc1.setOption(StandardSocketOptions.SO_REUSEADDR, true);
163 dc2.setOption(StandardSocketOptions.SO_REUSEADDR, true);
164
165 dc1.bind(new InetSocketAddress(group1, 0));
166 int port = dc1.socket().getLocalPort();
167 dc2.bind(new InetSocketAddress(group2, port));
168
169 System.out.format("dc1 joining [%s]:%d @ %s\n",
170 group1.getHostAddress(), port, nif.getName());
171 System.out.format("dc2 joining [%s]:%d @ %s\n",
172 group2.getHostAddress(), port, nif.getName());
173
174 dc1.join(group1, nif);
175 dc2.join(group2, nif);
176
177 int id = sendDatagram(nif, group1, port);
178
179 receiveDatagram(dc1, "dc1", true, id);
180 receiveDatagram(dc2, "dc2", false, id);
181
182 id = sendDatagram(nif, group2, port);
183
184 receiveDatagram(dc1, "dc1", false, id);
185 receiveDatagram(dc2, "dc2", true, id);
186
187 } finally {
189 dc2.close();
190 }
191 }
192
193 public static void main(String[] args) throws IOException {
194
195 String os = System.getProperty("os.name");
196
197 if (!os.equals("Linux")) {
198 throw new SkippedException("This test should be run only on Linux");
199 } else {
200 String osVersion = System.getProperty("os.version");
201 String prefix = "3.10.0";
202 if (osVersion.startsWith(prefix)) {
203 throw new SkippedException(
204 String.format("The behavior under test is known NOT to work on '%s' kernels", prefix));
205 }
206 }
207
208 NetworkConfiguration.printSystemConfiguration(System.out);
209
210 InetAddress interfaceLocal1 = InetAddress.getByName("ff11::2.3.4.5");
211 InetAddress interfaceLocal2 = InetAddress.getByName("ff11::6.7.8.9");
212
213 InetAddress linkLocal1 = InetAddress.getByName("ff12::2.3.4.5");
214 InetAddress linkLocal2 = InetAddress.getByName("ff12::6.7.8.9");
215
216 // get local network configuration to use
217 NetworkConfiguration config = NetworkConfiguration.probe();
218 boolean foundAtLeastOne = false;
219 for (NetworkInterface nif: config.ip6MulticastInterfaces()
220 .collect(Collectors.toList())) {
221 foundAtLeastOne = true;
222 test(INET6, nif, interfaceLocal1, interfaceLocal2);
223 test(INET6, nif, linkLocal1, linkLocal2);
224 }
225 if (!foundAtLeastOne) {
226 throw new SkippedException(
227 "No IPv6 interfaces that support multicast found");
228 }
229 }
230 }
|
1 /*
2 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23
24 /*
25 * @test
26 * @bug 8215294
27 * @requires os.family == "linux"
28 * @library /test/lib
29 * @build jdk.test.lib.NetworkConfiguration
30 * PromiscuousIPv6
31 * @run main PromiscuousIPv6
32 * @key randomness
33 */
34
35 import java.nio.ByteBuffer;
36 import java.nio.channels.*;
37 import java.net.*;
38 import java.util.*;
39 import java.io.IOException;
40 import jdk.test.lib.NetworkConfiguration;
41 import jtreg.SkippedException;
42 import static java.net.StandardProtocolFamily.*;
43 import static java.nio.charset.StandardCharsets.UTF_8;
44 import static java.util.stream.Collectors.toList;
45
46 /*
47 * This test was created as a copy of the Promiscuous test and adapted for
48 * IPv6 node-local and link-local multicast addresses on Linux.
49 */
50 public class PromiscuousIPv6 {
51
52 static final Random rand = new Random();
53
54 static final ProtocolFamily UNSPEC = () -> "UNSPEC";
55
56 /**
57 * Sends a datagram to the given multicast group
58 */
59 static int sendDatagram(NetworkInterface nif,
60 InetAddress group,
61 int port)
62 throws IOException
63 {
64 ProtocolFamily family = (group instanceof Inet6Address) ? INET6 : INET;
65 DatagramChannel dc = DatagramChannel.open(family)
66 .setOption(StandardSocketOptions.IP_MULTICAST_IF, nif);
67 int id = rand.nextInt();
68 byte[] msg = Integer.toString(id).getBytes(UTF_8);
69 ByteBuffer buf = ByteBuffer.wrap(msg);
70 System.out.format("Send message -> group %s (id=0x%x)\n",
71 group.getHostAddress(), id);
72 dc.send(buf, new InetSocketAddress(group, port));
73 dc.close();
74 return id;
75 }
76
77 /**
78 * Waits (with timeout) for datagram. The {@code datagramExpected}
79 * parameter indicates whether a datagram is expected, and if
80 * {@code true} then {@code id} is the identifier in the payload.
81 */
82 static void receiveDatagram(DatagramChannel dc,
83 String name,
84 boolean datagramExpected,
85 int id)
86 throws IOException
87 {
88 System.out.println("Checking if received by " + name);
89
90 Selector sel = Selector.open();
91 dc.configureBlocking(false);
92 dc.register(sel, SelectionKey.OP_READ);
93 ByteBuffer buf = ByteBuffer.allocateDirect(100);
94
95 try {
96 for (;;) {
97 System.out.println("Waiting to receive message");
98 sel.select(5*1000);
135 System.out.println("Message ignored (wrong sender)");
136 }
137
138 sel.selectedKeys().clear();
139 buf.rewind();
140 }
141 } finally {
142 sel.close();
143 }
144 }
145
146 static void test(ProtocolFamily family,
147 NetworkInterface nif,
148 InetAddress group1,
149 InetAddress group2)
150 throws IOException
151 {
152
153 System.out.format("%nTest family=%s%n", family.name());
154
155 // Bind addresses should include the same network interface / scope, so
156 // as to not reply on the default route when there are multiple interfaces
157 InetAddress bindAddr1 = Inet6Address.getByAddress(null, group1.getAddress(), nif);
158 InetAddress bindAddr2 = Inet6Address.getByAddress(null, group2.getAddress(), nif);
159
160 DatagramChannel dc1 = (family == UNSPEC) ?
161 DatagramChannel.open() : DatagramChannel.open(family);
162 DatagramChannel dc2 = (family == UNSPEC) ?
163 DatagramChannel.open() : DatagramChannel.open(family);
164
165 try {
166 dc1.setOption(StandardSocketOptions.SO_REUSEADDR, true);
167 dc2.setOption(StandardSocketOptions.SO_REUSEADDR, true);
168
169 dc1.bind(new InetSocketAddress(bindAddr1, 0));
170 int port = dc1.socket().getLocalPort();
171 dc2.bind(new InetSocketAddress(bindAddr2, port));
172
173 System.out.format("dc1 joining [%s]:%d @ %s\n",
174 group1.getHostAddress(), port, nif.getName());
175 System.out.format("dc2 joining [%s]:%d @ %s\n",
176 group2.getHostAddress(), port, nif.getName());
177
178 dc1.join(group1, nif);
179 dc2.join(group2, nif);
180
181 int id = sendDatagram(nif, group1, port);
182
183 receiveDatagram(dc1, "dc1", true, id);
184 receiveDatagram(dc2, "dc2", false, id);
185
186 id = sendDatagram(nif, group2, port);
187
188 receiveDatagram(dc1, "dc1", false, id);
189 receiveDatagram(dc2, "dc2", true, id);
190
191 } finally {
193 dc2.close();
194 }
195 }
196
197 public static void main(String[] args) throws IOException {
198
199 String os = System.getProperty("os.name");
200
201 if (!os.equals("Linux")) {
202 throw new SkippedException("This test should be run only on Linux");
203 } else {
204 String osVersion = System.getProperty("os.version");
205 String prefix = "3.10.0";
206 if (osVersion.startsWith(prefix)) {
207 throw new SkippedException(
208 String.format("The behavior under test is known NOT to work on '%s' kernels", prefix));
209 }
210 }
211
212 NetworkConfiguration.printSystemConfiguration(System.out);
213 List<NetworkInterface> nifs = NetworkConfiguration.probe()
214 .ip6MulticastInterfaces()
215 .collect(toList());
216
217 if (nifs.size() == 0) {
218 throw new SkippedException(
219 "No IPv6 interfaces that support multicast found");
220 }
221
222 InetAddress interfaceLocal1 = InetAddress.getByName("ff11::2.3.4.5");
223 InetAddress interfaceLocal2 = InetAddress.getByName("ff11::6.7.8.9");
224
225 InetAddress linkLocal1 = InetAddress.getByName("ff12::2.3.4.5");
226 InetAddress linkLocal2 = InetAddress.getByName("ff12::6.7.8.9");
227
228 for (NetworkInterface nif : nifs) {
229 test(INET6, nif, interfaceLocal1, interfaceLocal2);
230 test(INET6, nif, linkLocal1, linkLocal2);
231 }
232 }
233 }
|