1 /*
2  * Copyright (c) 2007, 2016, 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 4742177
27  * @summary Re-test IPv6 (and specifically MulticastSocket) with latest Linux & USAGI code
28  */
29 import java.util.*;
30 import java.net.*;
31 
32 public class NoLoopbackPackets {
33     private static String osname;
34 
isWindows()35     static boolean isWindows() {
36         if (osname == null)
37             osname = System.getProperty("os.name");
38         return osname.contains("Windows");
39     }
40 
hasIPv6()41     private static boolean hasIPv6() throws Exception {
42         List<NetworkInterface> nics = Collections.list(
43                                         NetworkInterface.getNetworkInterfaces());
44         for (NetworkInterface nic : nics) {
45             if (!nic.isLoopback()) {
46                 List<InetAddress> addrs = Collections.list(nic.getInetAddresses());
47                 for (InetAddress addr : addrs) {
48                     if (addr instanceof Inet6Address) {
49                         return true;
50                     }
51                 }
52             }
53         }
54 
55         return false;
56     }
57 
main(String[] args)58     public static void main(String[] args) throws Exception {
59         if (isWindows()) {
60             System.out.println("The test only run on non-Windows OS. Bye.");
61             return;
62         }
63 
64         if (!hasIPv6()) {
65             System.out.println("No IPv6 available. Bye.");
66             return;
67         }
68 
69         MulticastSocket msock = null;
70         List<SocketAddress> failedGroups = new ArrayList<SocketAddress>();
71         Sender sender = null;
72         try {
73             msock = new MulticastSocket();
74             int port = msock.getLocalPort();
75 
76             // we will send packets to three multicast groups :-
77             // 224.1.1.1, ::ffff:224.1.1.2, and ff02::1:1
78             //
79             List<SocketAddress> groups = new ArrayList<SocketAddress>();
80             groups.add(new InetSocketAddress(InetAddress.getByName("224.1.1.1"), port));
81             groups.add(new InetSocketAddress(InetAddress.getByName("::ffff:224.1.1.2"), port));
82             groups.add(new InetSocketAddress(InetAddress.getByName("ff02::1:1"), port));
83 
84             sender = new Sender(groups);
85             new Thread(sender).start();
86 
87             // Now try to receive multicast packets. we should not see any of them
88             // since we disable loopback mode.
89             //
90             msock.setSoTimeout(5000);       // 5 seconds
91 
92             byte[] buf = new byte[1024];
93             DatagramPacket packet = new DatagramPacket(buf, 0, buf.length);
94             for (SocketAddress group : groups) {
95                 msock.joinGroup(group, null);
96 
97                 try {
98                     msock.receive(packet);
99 
100                     // it is an error if we receive something
101                     failedGroups.add(group);
102                 } catch (SocketTimeoutException e) {
103                     // we expect this
104                 }
105 
106                 msock.leaveGroup(group, null);
107             }
108         } finally {
109             if (msock != null) try { msock.close(); } catch (Exception e) {}
110             if (sender != null) {
111                 sender.stop();
112             }
113         }
114 
115         if (failedGroups.size() > 0) {
116             System.out.println("We should not receive anything from following groups, but we did:");
117             for (SocketAddress group : failedGroups)
118                 System.out.println(group);
119             throw new RuntimeException("test failed.");
120         }
121     }
122 
123     static class Sender implements Runnable {
124         private List<SocketAddress> sendToGroups;
125         private volatile boolean stop;
126 
Sender(List<SocketAddress> groups)127         public Sender(List<SocketAddress> groups) {
128             sendToGroups = groups;
129         }
130 
run()131         public void run() {
132             byte[] buf = "hello world".getBytes();
133             List<DatagramPacket> packets = new ArrayList<DatagramPacket>();
134 
135             try {
136                 for (SocketAddress group : sendToGroups) {
137                     DatagramPacket packet = new DatagramPacket(buf, buf.length, group);
138                     packets.add(packet);
139                 }
140 
141                 MulticastSocket msock = new MulticastSocket();
142                 msock.setLoopbackMode(true);    // disable loopback mode
143                 while (!stop) {
144                     for (DatagramPacket packet : packets) {
145                         msock.send(packet);
146                     }
147 
148                     Thread.sleep(1000);     // 1 second
149                 }
150             } catch (Exception e) {
151                 throw new RuntimeException(e);
152             }
153         }
154 
stop()155         void stop() {
156             stop = true;
157         }
158     }
159 }
160