1 /* 2 * Copyright (c) 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 import com.sun.jdi.Bootstrap; 25 import com.sun.jdi.VirtualMachine; 26 import com.sun.jdi.connect.AttachingConnector; 27 import com.sun.jdi.connect.Connector; 28 import com.sun.jdi.connect.IllegalConnectorArgumentsException; 29 import lib.jdb.Debuggee; 30 31 import java.io.IOException; 32 import java.net.Inet4Address; 33 import java.net.Inet6Address; 34 import java.net.InetAddress; 35 import java.util.Iterator; 36 import java.util.LinkedList; 37 import java.util.List; 38 import java.util.Map; 39 40 /* 41 * @test 42 * @bug 8184770 43 * @summary Tests that JDWP agent honors jdk net properties 44 * @library /test/lib 45 * 46 * @build HelloWorld JdwpNetProps 47 * @run main/othervm JdwpNetProps 48 */ 49 public class JdwpNetProps { 50 main(String[] args)51 public static void main(String[] args) throws Exception { 52 InetAddress addrs[] = InetAddress.getAllByName("localhost"); 53 InetAddress ipv4Address = null; 54 InetAddress ipv6Address = null; 55 for (int i = 0; i < addrs.length; i++) { 56 if (addrs[i] instanceof Inet4Address) { 57 ipv4Address = addrs[i]; 58 } else if (addrs[i] instanceof Inet6Address) { 59 ipv6Address = addrs[i]; 60 } 61 } 62 63 if (ipv4Address != null) { 64 new ListenTest("localhost", ipv4Address) 65 .preferIPv4Stack(true) 66 .run(TestResult.Success); 67 new ListenTest("localhost", ipv4Address) 68 .preferIPv4Stack(false) 69 .run(TestResult.Success); 70 if (ipv6Address != null) { 71 // - only IPv4, so connection prom IPv6 should fail 72 new ListenTest("localhost", ipv6Address) 73 .preferIPv4Stack(true) 74 .preferIPv6Addresses(true) 75 .run(TestResult.AttachFailed); 76 // - listen on IPv4 77 new ListenTest("localhost", ipv6Address) 78 .preferIPv6Addresses(false) 79 .run(TestResult.AttachFailed); 80 // - listen on IPv6 81 new ListenTest("localhost", ipv6Address) 82 .preferIPv6Addresses(true) 83 .run(TestResult.Success); 84 } 85 } else { 86 // IPv6-only system - expected to fail on IPv4 address 87 new ListenTest("localhost", ipv6Address) 88 .preferIPv4Stack(true) 89 .run(TestResult.ListenFailed); 90 } 91 } 92 93 private enum TestResult { 94 Success, 95 ListenFailed, 96 AttachFailed 97 } 98 99 private static class ListenTest { 100 private final String listenAddress; 101 private final InetAddress connectAddress; 102 private Boolean preferIPv4Stack; 103 private Boolean preferIPv6Addresses; ListenTest(String listenAddress, InetAddress connectAddress)104 public ListenTest(String listenAddress, InetAddress connectAddress) { 105 this.listenAddress = listenAddress; 106 this.connectAddress = connectAddress; 107 } preferIPv4Stack(Boolean value)108 public ListenTest preferIPv4Stack(Boolean value) { 109 preferIPv4Stack = value; 110 return this; 111 } preferIPv6Addresses(Boolean value)112 public ListenTest preferIPv6Addresses(Boolean value) { 113 preferIPv6Addresses = value; 114 return this; 115 } 116 run(TestResult expectedResult)117 public void run(TestResult expectedResult) throws Exception { 118 List<String> options = new LinkedList<>(); 119 if (preferIPv4Stack != null) { 120 options.add("-Djava.net.preferIPv4Stack=" + preferIPv4Stack.toString()); 121 } 122 if (preferIPv6Addresses != null) { 123 options.add("-Djava.net.preferIPv6Addresses=" + preferIPv6Addresses.toString()); 124 } 125 log("Starting listening debuggee at " + listenAddress 126 + (expectedResult == TestResult.ListenFailed ? ": expected to fail" : "")); 127 Exception error = null; 128 try (Debuggee debuggee = Debuggee.launcher("HelloWorld") 129 .setAddress(listenAddress + ":0") 130 .addOptions(options).launch()) { 131 log("Debuggee is listening on " + listenAddress + ":" + debuggee.getAddress()); 132 log("Connecting from " + connectAddress.getHostAddress() 133 + ", expected: " + (expectedResult == TestResult.Success ? "Success" : "Failure")); 134 try { 135 VirtualMachine vm = attach(connectAddress.getHostAddress(), debuggee.getAddress()); 136 vm.dispose(); 137 if (expectedResult == TestResult.Success) { 138 log("Attached successfully (as expected)"); 139 } else { 140 error = new RuntimeException("ERROR: attached successfully"); 141 } 142 } catch (Exception ex) { 143 if (expectedResult == TestResult.AttachFailed) { 144 log("Attach failed (as expected)"); 145 } else { 146 error = new RuntimeException("ERROR: failed to attach", ex); 147 } 148 } 149 } catch (Exception ex) { 150 if (expectedResult == TestResult.ListenFailed) { 151 log("Listen failed (as expected)"); 152 } else { 153 error = new RuntimeException("ERROR: listen failed", ex); 154 } 155 } 156 if (error != null) { 157 throw error; 158 } 159 } 160 } 161 162 private static String ATTACH_CONNECTOR = "com.sun.jdi.SocketAttach"; 163 // cache socket attaching connector 164 private static AttachingConnector attachingConnector; 165 attach(String address, String port)166 private static VirtualMachine attach(String address, String port) throws IOException { 167 if (attachingConnector == null) { 168 attachingConnector = (AttachingConnector)getConnector(ATTACH_CONNECTOR); 169 } 170 Map<String, Connector.Argument> args = attachingConnector.defaultArguments(); 171 setConnectorArg(args, "hostname", address); 172 setConnectorArg(args, "port", port); 173 try { 174 return attachingConnector.attach(args); 175 } catch (IllegalConnectorArgumentsException e) { 176 // unexpected.. wrap in RuntimeException 177 throw new RuntimeException(e); 178 } 179 } 180 getConnector(String name)181 private static Connector getConnector(String name) { 182 List<Connector> connectors = Bootstrap.virtualMachineManager().allConnectors(); 183 for (Iterator<Connector> iter = connectors.iterator(); iter.hasNext(); ) { 184 Connector connector = iter.next(); 185 if (connector.name().equalsIgnoreCase(name)) { 186 return connector; 187 } 188 } 189 throw new IllegalArgumentException("Connector " + name + " not found"); 190 } 191 setConnectorArg(Map<String, Connector.Argument> args, String name, String value)192 private static void setConnectorArg(Map<String, Connector.Argument> args, String name, String value) { 193 Connector.Argument arg = args.get(name); 194 if (arg == null) { 195 throw new IllegalArgumentException("Argument " + name + " is not defined"); 196 } 197 arg.setValue(value); 198 } 199 log(Object o)200 private static void log(Object o) { 201 System.out.println(String.valueOf(o)); 202 } 203 204 } 205