1/* 2 * Copyright (c) 2007, 2017, 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 */ 29import java.net.*; 30import java.util.*; 31 32 33public class SetOutgoingIf { 34 private static int PORT = 9001; 35 private static String osname; 36 37 static boolean isWindows() { 38 if (osname == null) 39 osname = System.getProperty("os.name"); 40 return osname.contains("Windows"); 41 } 42 43 static boolean isMacOS() { 44 return System.getProperty("os.name").contains("OS X"); 45 } 46 47 private static boolean hasIPv6() throws Exception { 48 List<NetworkInterface> nics = Collections.list( 49 NetworkInterface.getNetworkInterfaces()); 50 for (NetworkInterface nic : nics) { 51 List<InetAddress> addrs = Collections.list(nic.getInetAddresses()); 52 for (InetAddress addr : addrs) { 53 if (addr instanceof Inet6Address) 54 return true; 55 } 56 } 57 58 return false; 59 } 60 61 public static void main(String[] args) throws Exception { 62 if (isWindows()) { 63 System.out.println("The test only run on non-Windows OS. Bye."); 64 return; 65 } 66 67 if (!hasIPv6()) { 68 System.out.println("No IPv6 available. Bye."); 69 return; 70 } 71 72 // We need 2 or more network interfaces to run the test 73 // 74 List<NetIf> netIfs = new ArrayList<NetIf>(); 75 int index = 1; 76 for (NetworkInterface nic : Collections.list(NetworkInterface.getNetworkInterfaces())) { 77 // we should use only network interfaces with multicast support which are in "up" state 78 if (!nic.isLoopback() && nic.supportsMulticast() && nic.isUp() && !isTestExcludedInterface(nic)) { 79 NetIf netIf = NetIf.create(nic); 80 81 // now determine what (if any) type of addresses are assigned to this interface 82 for (InetAddress addr : Collections.list(nic.getInetAddresses())) { 83 if (addr.isAnyLocalAddress()) 84 continue; 85 86 System.out.println(" addr " + addr); 87 if (addr instanceof Inet4Address) { 88 netIf.ipv4Address(true); 89 } else if (addr instanceof Inet6Address) { 90 netIf.ipv6Address(true); 91 } 92 } 93 if (netIf.ipv4Address() || netIf.ipv6Address()) { 94 netIf.index(index++); 95 netIfs.add(netIf); 96 debug("Using: " + nic); 97 } 98 } else { 99 System.out.println("Ignore NetworkInterface nic == " + nic); 100 } 101 } 102 if (netIfs.size() <= 1) { 103 System.out.println("Need 2 or more network interfaces to run. Bye."); 104 return; 105 } 106 107 // We will send packets to one ipv4, and one ipv6 108 // multicast group using each network interface :- 109 // 224.1.1.1 --| 110 // ff02::1:1 --|--> using network interface #1 111 // 224.1.2.1 --| 112 // ff02::1:2 --|--> using network interface #2 113 // and so on. 114 // 115 for (NetIf netIf : netIfs) { 116 int NetIfIndex = netIf.index(); 117 List<InetAddress> groups = new ArrayList<InetAddress>(); 118 119 if (netIf.ipv4Address()) { 120 InetAddress groupv4 = InetAddress.getByName("224.1." + NetIfIndex + ".1"); 121 groups.add(groupv4); 122 } 123 if (netIf.ipv6Address()) { 124 InetAddress groupv6 = InetAddress.getByName("ff02::1:" + NetIfIndex); 125 groups.add(groupv6); 126 } 127 128 debug("Adding " + groups + " groups for " + netIf.nic().getName()); 129 netIf.groups(groups); 130 131 // use a separated thread to send to those 2 groups 132 Thread sender = new Thread(new Sender(netIf, 133 groups, 134 PORT)); 135 sender.setDaemon(true); // we want sender to stop when main thread exits 136 sender.start(); 137 } 138 139 // try to receive on each group, then check if the packet comes 140 // from the expected network interface 141 // 142 byte[] buf = new byte[1024]; 143 for (NetIf netIf : netIfs) { 144 NetworkInterface nic = netIf.nic(); 145 for (InetAddress group : netIf.groups()) { 146 MulticastSocket mcastsock = new MulticastSocket(PORT); 147 mcastsock.setSoTimeout(5000); // 5 second 148 DatagramPacket packet = new DatagramPacket(buf, 0, buf.length); 149 150 // the interface supports the IP multicast group 151 debug("Joining " + group + " on " + nic.getName()); 152 mcastsock.joinGroup(new InetSocketAddress(group, PORT), nic); 153 154 try { 155 mcastsock.receive(packet); 156 debug("received packet on " + packet.getAddress()); 157 } catch (Exception e) { 158 // test failed if any exception 159 throw new RuntimeException(e); 160 } 161 162 // now check which network interface this packet comes from 163 NetworkInterface from = NetworkInterface.getByInetAddress(packet.getAddress()); 164 NetworkInterface shouldbe = nic; 165 if (from != null) { 166 if (!from.equals(shouldbe)) { 167 System.out.println("Packets on group " 168 + group + " should come from " 169 + shouldbe.getName() + ", but came from " 170 + from.getName()); 171 } 172 } 173 174 mcastsock.leaveGroup(new InetSocketAddress(group, PORT), nic); 175 } 176 } 177 } 178 179 private static boolean isTestExcludedInterface(NetworkInterface nif) { 180 if (isMacOS() && nif.getName().contains("awdl")) 181 return true; 182 String dName = nif.getDisplayName(); 183 if (isWindows() && dName != null && dName.contains("Teredo")) 184 return true; 185 return false; 186 } 187 188 private static boolean debug = true; 189 190 static void debug(String message) { 191 if (debug) 192 System.out.println(message); 193 } 194} 195 196class Sender implements Runnable { 197 private NetIf netIf; 198 private List<InetAddress> groups; 199 private int port; 200 201 public Sender(NetIf netIf, 202 List<InetAddress> groups, 203 int port) { 204 this.netIf = netIf; 205 this.groups = groups; 206 this.port = port; 207 } 208 209 public void run() { 210 try { 211 MulticastSocket mcastsock = new MulticastSocket(); 212 mcastsock.setNetworkInterface(netIf.nic()); 213 List<DatagramPacket> packets = new LinkedList<DatagramPacket>(); 214 215 byte[] buf = "hello world".getBytes(); 216 for (InetAddress group : groups) { 217 packets.add(new DatagramPacket(buf, buf.length, new InetSocketAddress(group, port))); 218 } 219 220 for (;;) { 221 for (DatagramPacket packet : packets) 222 mcastsock.send(packet); 223 224 Thread.sleep(1000); // sleep 1 second 225 } 226 } catch (Exception e) { 227 throw new RuntimeException(e); 228 } 229 } 230} 231 232@SuppressWarnings("unchecked") 233class NetIf { 234 private boolean ipv4Address; //false 235 private boolean ipv6Address; //false 236 private int index; 237 List<InetAddress> groups = Collections.EMPTY_LIST; 238 private final NetworkInterface nic; 239 240 private NetIf(NetworkInterface nic) { 241 this.nic = nic; 242 } 243 244 static NetIf create(NetworkInterface nic) { 245 return new NetIf(nic); 246 } 247 248 NetworkInterface nic() { 249 return nic; 250 } 251 252 boolean ipv4Address() { 253 return ipv4Address; 254 } 255 256 void ipv4Address(boolean ipv4Address) { 257 this.ipv4Address = ipv4Address; 258 } 259 260 boolean ipv6Address() { 261 return ipv6Address; 262 } 263 264 void ipv6Address(boolean ipv6Address) { 265 this.ipv6Address = ipv6Address; 266 } 267 268 int index() { 269 return index; 270 } 271 272 void index(int index) { 273 this.index = index; 274 } 275 276 List<InetAddress> groups() { 277 return groups; 278 } 279 280 void groups(List<InetAddress> groups) { 281 this.groups = groups; 282 } 283} 284 285