1 /*
2 * Copyright (c) 2000, 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.nio.ch;
27
28 import java.io.FileDescriptor;
29 import java.io.IOException;
30 import java.net.Inet4Address;
31 import java.net.Inet6Address;
32 import java.net.InetAddress;
33 import java.net.InetSocketAddress;
34 import java.net.NetworkInterface;
35 import java.net.ProtocolFamily;
36 import java.net.SocketAddress;
37 import java.net.SocketException;
38 import java.net.SocketOption;
39 import java.net.StandardProtocolFamily;
40 import java.net.StandardSocketOptions;
41 import java.net.UnknownHostException;
42 import java.nio.channels.AlreadyBoundException;
43 import java.nio.channels.ClosedChannelException;
44 import java.nio.channels.NotYetBoundException;
45 import java.nio.channels.NotYetConnectedException;
46 import java.nio.channels.UnresolvedAddressException;
47 import java.nio.channels.UnsupportedAddressTypeException;
48 import java.security.AccessController;
49 import java.security.PrivilegedAction;
50 import java.util.Enumeration;
51
52 import sun.net.ext.ExtendedSocketOptions;
53 import sun.net.util.IPAddressUtil;
54 import sun.security.action.GetPropertyAction;
55
56 public class Net {
57
58 private Net() { }
59
60 // unspecified protocol family
61 static final ProtocolFamily UNSPEC = new ProtocolFamily() {
62 public String name() {
63 return "UNSPEC";
64 }
65 };
66
67 // set to true if exclusive binding is on for Windows
68 private static final boolean exclusiveBind;
69
70 // set to true if the fast tcp loopback should be enabled on Windows
71 private static final boolean fastLoopback;
72
73 // -- Miscellaneous utilities --
74
75 private static volatile boolean checkedIPv6;
76 private static volatile boolean isIPv6Available;
77 private static volatile boolean checkedReusePort;
78 private static volatile boolean isReusePortAvailable;
79
80 /**
81 * Tells whether dual-IPv4/IPv6 sockets should be used.
82 */
83 static boolean isIPv6Available() {
84 if (!checkedIPv6) {
85 isIPv6Available = isIPv6Available0();
86 checkedIPv6 = true;
87 }
88 return isIPv6Available;
89 }
90
91 /**
92 * Tells whether SO_REUSEPORT is supported.
93 */
94 static boolean isReusePortAvailable() {
95 if (!checkedReusePort) {
96 isReusePortAvailable = isReusePortAvailable0();
97 checkedReusePort = true;
98 }
99 return isReusePortAvailable;
100 }
101
102 /**
103 * Returns true if exclusive binding is on
104 */
105 static boolean useExclusiveBind() {
106 return exclusiveBind;
107 }
108
109 /**
110 * Tells whether IPv6 sockets can join IPv4 multicast groups
111 */
112 static boolean canIPv6SocketJoinIPv4Group() {
113 return canIPv6SocketJoinIPv4Group0();
114 }
115
116 /**
117 * Tells whether {@link #join6} can be used to join an IPv4
118 * multicast group (IPv4 group as IPv4-mapped IPv6 address)
119 */
120 static boolean canJoin6WithIPv4Group() {
121 return canJoin6WithIPv4Group0();
122 }
123
124 public static InetSocketAddress checkAddress(SocketAddress sa) {
125 if (sa == null)
126 throw new NullPointerException();
127 if (!(sa instanceof InetSocketAddress))
128 throw new UnsupportedAddressTypeException(); // ## needs arg
129 InetSocketAddress isa = (InetSocketAddress)sa;
130 if (isa.isUnresolved())
131 throw new UnresolvedAddressException(); // ## needs arg
132 InetAddress addr = isa.getAddress();
133 if (!(addr instanceof Inet4Address || addr instanceof Inet6Address))
134 throw new IllegalArgumentException("Invalid address type");
135 return isa;
136 }
137
138 static InetSocketAddress checkAddress(SocketAddress sa, ProtocolFamily family) {
139 InetSocketAddress isa = checkAddress(sa);
140 if (family == StandardProtocolFamily.INET) {
141 InetAddress addr = isa.getAddress();
142 if (!(addr instanceof Inet4Address))
143 throw new UnsupportedAddressTypeException();
144 }
145 return isa;
146 }
147
148 static InetSocketAddress asInetSocketAddress(SocketAddress sa) {
149 if (!(sa instanceof InetSocketAddress))
150 throw new UnsupportedAddressTypeException();
151 return (InetSocketAddress)sa;
152 }
153
154 static void translateToSocketException(Exception x)
155 throws SocketException
156 {
157 if (x instanceof SocketException)
158 throw (SocketException)x;
159 Exception nx = x;
160 if (x instanceof ClosedChannelException)
161 nx = new SocketException("Socket is closed");
162 else if (x instanceof NotYetConnectedException)
163 nx = new SocketException("Socket is not connected");
164 else if (x instanceof AlreadyBoundException)
165 nx = new SocketException("Already bound");
166 else if (x instanceof NotYetBoundException)
167 nx = new SocketException("Socket is not bound yet");
168 else if (x instanceof UnsupportedAddressTypeException)
169 nx = new SocketException("Unsupported address type");
170 else if (x instanceof UnresolvedAddressException) {
171 nx = new SocketException("Unresolved address");
172 }
173 if (nx != x)
174 nx.initCause(x);
175
176 if (nx instanceof SocketException)
177 throw (SocketException)nx;
178 else if (nx instanceof RuntimeException)
179 throw (RuntimeException)nx;
180 else
181 throw new Error("Untranslated exception", nx);
182 }
183
184 static void translateException(Exception x,
185 boolean unknownHostForUnresolved)
186 throws IOException
187 {
188 if (x instanceof IOException)
189 throw (IOException)x;
190 // Throw UnknownHostException from here since it cannot
191 // be thrown as a SocketException
192 if (unknownHostForUnresolved &&
193 (x instanceof UnresolvedAddressException))
194 {
195 throw new UnknownHostException();
196 }
197 translateToSocketException(x);
198 }
199
200 static void translateException(Exception x)
201 throws IOException
202 {
203 translateException(x, false);
204 }
205
206 /**
207 * Returns the local address after performing a SecurityManager#checkConnect.
208 */
209 static InetSocketAddress getRevealedLocalAddress(InetSocketAddress addr) {
210 SecurityManager sm = System.getSecurityManager();
211 if (addr == null || sm == null)
212 return addr;
213
214 try{
215 sm.checkConnect(addr.getAddress().getHostAddress(), -1);
216 // Security check passed
217 } catch (SecurityException e) {
218 // Return loopback address only if security check fails
219 addr = getLoopbackAddress(addr.getPort());
220 }
221 return addr;
222 }
223
224 static String getRevealedLocalAddressAsString(InetSocketAddress addr) {
225 return System.getSecurityManager() == null ? addr.toString() :
226 getLoopbackAddress(addr.getPort()).toString();
227 }
228
229 private static InetSocketAddress getLoopbackAddress(int port) {
230 return new InetSocketAddress(InetAddress.getLoopbackAddress(),
231 port);
232 }
233
234 /**
235 * Returns any IPv4 address of the given network interface, or
236 * null if the interface does not have any IPv4 addresses.
237 */
238 static Inet4Address anyInet4Address(final NetworkInterface interf) {
239 return AccessController.doPrivileged(new PrivilegedAction<Inet4Address>() {
240 public Inet4Address run() {
241 Enumeration<InetAddress> addrs = interf.getInetAddresses();
242 while (addrs.hasMoreElements()) {
243 InetAddress addr = addrs.nextElement();
244 if (addr instanceof Inet4Address) {
245 return (Inet4Address)addr;
246 }
247 }
248 return null;
249 }
250 });
251 }
252
253 /**
254 * Returns an IPv4 address as an int.
255 */
256 static int inet4AsInt(InetAddress ia) {
257 if (ia instanceof Inet4Address) {
258 byte[] addr = ia.getAddress();
259 int address = addr[3] & 0xFF;
260 address |= ((addr[2] << 8) & 0xFF00);
261 address |= ((addr[1] << 16) & 0xFF0000);
262 address |= ((addr[0] << 24) & 0xFF000000);
263 return address;
264 }
265 throw new AssertionError("Should not reach here");
266 }
267
268 /**
269 * Returns an InetAddress from the given IPv4 address
270 * represented as an int.
271 */
272 static InetAddress inet4FromInt(int address) {
273 byte[] addr = new byte[4];
274 addr[0] = (byte) ((address >>> 24) & 0xFF);
275 addr[1] = (byte) ((address >>> 16) & 0xFF);
276 addr[2] = (byte) ((address >>> 8) & 0xFF);
277 addr[3] = (byte) (address & 0xFF);
278 try {
279 return InetAddress.getByAddress(addr);
280 } catch (UnknownHostException uhe) {
281 throw new AssertionError("Should not reach here");
282 }
283 }
284
285 /**
286 * Returns an IPv6 address as a byte array
287 */
288 static byte[] inet6AsByteArray(InetAddress ia) {
289 if (ia instanceof Inet6Address) {
290 return ia.getAddress();
291 }
292
293 // need to construct IPv4-mapped address
294 if (ia instanceof Inet4Address) {
295 byte[] ip4address = ia.getAddress();
296 byte[] address = new byte[16];
297 address[10] = (byte)0xff;
298 address[11] = (byte)0xff;
299 address[12] = ip4address[0];
300 address[13] = ip4address[1];
301 address[14] = ip4address[2];
302 address[15] = ip4address[3];
303 return address;
304 }
305
306 throw new AssertionError("Should not reach here");
307 }
308
309 // -- Socket options
310
311 static final ExtendedSocketOptions extendedOptions =
312 ExtendedSocketOptions.getInstance();
313
314 static void setSocketOption(FileDescriptor fd, SocketOption<?> name, Object value)
315 throws IOException
316 {
317 setSocketOption(fd, Net.UNSPEC, name, value);
318 }
319
320 static void setSocketOption(FileDescriptor fd, ProtocolFamily family,
321 SocketOption<?> name, Object value)
322 throws IOException
323 {
324 if (value == null)
325 throw new IllegalArgumentException("Invalid option value");
326
327 // only simple values supported by this method
328 Class<?> type = name.type();
329
330 if (extendedOptions.isOptionSupported(name)) {
331 extendedOptions.setOption(fd, name, value);
332 return;
333 }
334
335 if (type != Integer.class && type != Boolean.class)
336 throw new AssertionError("Should not reach here");
337
338 // special handling
339 if (name == StandardSocketOptions.SO_RCVBUF ||
340 name == StandardSocketOptions.SO_SNDBUF)
341 {
342 int i = ((Integer)value).intValue();
343 if (i < 0)
344 throw new IllegalArgumentException("Invalid send/receive buffer size");
345 }
346 if (name == StandardSocketOptions.SO_LINGER) {
347 int i = ((Integer)value).intValue();
348 if (i < 0)
349 value = Integer.valueOf(-1);
350 if (i > 65535)
351 value = Integer.valueOf(65535);
352 }
353 if (name == StandardSocketOptions.IP_TOS) {
354 int i = ((Integer)value).intValue();
355 if (i < 0 || i > 255)
356 throw new IllegalArgumentException("Invalid IP_TOS value");
357 }
358 if (name == StandardSocketOptions.IP_MULTICAST_TTL) {
359 int i = ((Integer)value).intValue();
360 if (i < 0 || i > 255)
361 throw new IllegalArgumentException("Invalid TTL/hop value");
362 }
363
364 // map option name to platform level/name
365 OptionKey key = SocketOptionRegistry.findOption(name, family);
366 if (key == null)
367 throw new AssertionError("Option not found");
368
369 int arg;
370 if (type == Integer.class) {
371 arg = ((Integer)value).intValue();
372 } else {
373 boolean b = ((Boolean)value).booleanValue();
374 arg = (b) ? 1 : 0;
375 }
376
377 boolean mayNeedConversion = (family == UNSPEC);
378 boolean isIPv6 = (family == StandardProtocolFamily.INET6);
379 setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg, isIPv6);
380 }
381
382 static Object getSocketOption(FileDescriptor fd, SocketOption<?> name)
383 throws IOException
384 {
385 return getSocketOption(fd, Net.UNSPEC, name);
386 }
387
388 static Object getSocketOption(FileDescriptor fd, ProtocolFamily family, SocketOption<?> name)
389 throws IOException
390 {
391 Class<?> type = name.type();
392
393 if (extendedOptions.isOptionSupported(name)) {
394 return extendedOptions.getOption(fd, name);
395 }
396
397 // only simple values supported by this method
398 if (type != Integer.class && type != Boolean.class)
399 throw new AssertionError("Should not reach here");
400
401 // map option name to platform level/name
402 OptionKey key = SocketOptionRegistry.findOption(name, family);
403 if (key == null)
404 throw new AssertionError("Option not found");
405
406 boolean mayNeedConversion = (family == UNSPEC);
407 int value = getIntOption0(fd, mayNeedConversion, key.level(), key.name());
408
409 if (type == Integer.class) {
410 return Integer.valueOf(value);
411 } else {
412 return (value == 0) ? Boolean.FALSE : Boolean.TRUE;
413 }
414 }
415
416 public static boolean isFastTcpLoopbackRequested() {
417 String loopbackProp = GetPropertyAction
418 .privilegedGetProperty("jdk.net.useFastTcpLoopback", "false");
419 return loopbackProp.isEmpty() ? true : Boolean.parseBoolean(loopbackProp);
420 }
421
422 // -- Socket operations --
423
424 private static native boolean isIPv6Available0();
425
426 private static native boolean isReusePortAvailable0();
427
428 /*
429 * Returns 1 for Windows and -1 for Solaris/Linux/Mac OS
430 */
431 private static native int isExclusiveBindAvailable();
432
433 private static native boolean canIPv6SocketJoinIPv4Group0();
434
435 private static native boolean canJoin6WithIPv4Group0();
436
437 static FileDescriptor socket(boolean stream) throws IOException {
438 return socket(UNSPEC, stream);
439 }
440
441 static FileDescriptor socket(ProtocolFamily family, boolean stream) throws IOException {
442 boolean preferIPv6 = isIPv6Available() &&
443 (family != StandardProtocolFamily.INET);
444 return IOUtil.newFD(socket0(preferIPv6, stream, false, fastLoopback));
445 }
446
447 static FileDescriptor serverSocket(boolean stream) {
448 return IOUtil.newFD(socket0(isIPv6Available(), stream, true, fastLoopback));
449 }
450
451 // Due to oddities SO_REUSEADDR on windows reuse is ignored
452 private static native int socket0(boolean preferIPv6, boolean stream, boolean reuse,
453 boolean fastLoopback);
454
455 public static void bind(FileDescriptor fd, InetAddress addr, int port)
456 throws IOException
457 {
458 bind(UNSPEC, fd, addr, port);
459 }
460
461 static void bind(ProtocolFamily family, FileDescriptor fd,
462 InetAddress addr, int port) throws IOException
463 {
464 boolean preferIPv6 = isIPv6Available() &&
465 (family != StandardProtocolFamily.INET);
466 if (addr.isLinkLocalAddress()) {
467 addr = IPAddressUtil.toScopedAddress(addr);
468 }
469 bind0(fd, preferIPv6, exclusiveBind, addr, port);
470 }
471
472 private static native void bind0(FileDescriptor fd, boolean preferIPv6,
473 boolean useExclBind, InetAddress addr,
474 int port)
475 throws IOException;
476
477 static native void listen(FileDescriptor fd, int backlog) throws IOException;
478
479 static int connect(FileDescriptor fd, InetAddress remote, int remotePort)
480 throws IOException
481 {
482 return connect(UNSPEC, fd, remote, remotePort);
483 }
484
485 static int connect(ProtocolFamily family, FileDescriptor fd, InetAddress remote, int remotePort)
486 throws IOException
487 {
488 if (remote.isLinkLocalAddress()) {
489 remote = IPAddressUtil.toScopedAddress(remote);
490 }
491 boolean preferIPv6 = isIPv6Available() &&
492 (family != StandardProtocolFamily.INET);
493 return connect0(preferIPv6, fd, remote, remotePort);
494 }
495
496 private static native int connect0(boolean preferIPv6,
497 FileDescriptor fd,
498 InetAddress remote,
499 int remotePort)
500 throws IOException;
501
502 public static native int accept(FileDescriptor fd,
503 FileDescriptor newfd,
504 InetSocketAddress[] isaa)
505 throws IOException;
506
507 public static final int SHUT_RD = 0;
508 public static final int SHUT_WR = 1;
509 public static final int SHUT_RDWR = 2;
510
511 static native void shutdown(FileDescriptor fd, int how) throws IOException;
512
513 private static native int localPort(FileDescriptor fd)
514 throws IOException;
515
516 private static native InetAddress localInetAddress(FileDescriptor fd)
517 throws IOException;
518
519 public static InetSocketAddress localAddress(FileDescriptor fd)
520 throws IOException
521 {
522 return new InetSocketAddress(localInetAddress(fd), localPort(fd));
523 }
524
525 private static native int remotePort(FileDescriptor fd)
526 throws IOException;
527
528 private static native InetAddress remoteInetAddress(FileDescriptor fd)
529 throws IOException;
530
531 static InetSocketAddress remoteAddress(FileDescriptor fd)
532 throws IOException
533 {
534 return new InetSocketAddress(remoteInetAddress(fd), remotePort(fd));
535 }
536
537 private static native int getIntOption0(FileDescriptor fd, boolean mayNeedConversion,
538 int level, int opt)
539 throws IOException;
540
541 private static native void setIntOption0(FileDescriptor fd, boolean mayNeedConversion,
542 int level, int opt, int arg, boolean isIPv6)
543 throws IOException;
544
545 /**
546 * Polls a file descriptor for events.
547 * @param timeout the timeout to wait; 0 to not wait, -1 to wait indefinitely
548 * @return the polled events or 0 if no events are polled
549 */
550 static native int poll(FileDescriptor fd, int events, long timeout)
551 throws IOException;
552
553 /**
554 * Performs a non-blocking poll of a file descriptor.
555 * @return the polled events or 0 if no events are polled
556 */
557 static int pollNow(FileDescriptor fd, int events) throws IOException {
558 return poll(fd, events, 0);
559 }
560
561 /**
562 * Polls a connecting socket to test if the connection has been established.
563 *
564 * @apiNote This method is public to allow it be used by code in jdk.sctp.
565 *
566 * @param timeout the timeout to wait; 0 to not wait, -1 to wait indefinitely
567 * @return true if connected
568 */
569 public static native boolean pollConnect(FileDescriptor fd, long timeout)
570 throws IOException;
571
572 /**
573 * Performs a non-blocking poll of a connecting socket to test if the
574 * connection has been established.
575 *
576 * @return true if connected
577 */
578 static boolean pollConnectNow(FileDescriptor fd) throws IOException {
579 return pollConnect(fd, 0);
580 }
581
582 /**
583 * Return the number of bytes in the socket input buffer.
584 */
585 static native int available(FileDescriptor fd) throws IOException;
586
587 /**
588 * Send one byte of urgent data (MSG_OOB) on the socket.
589 */
590 static native int sendOOB(FileDescriptor fd, byte data) throws IOException;
591
592
593 // -- Multicast support --
594
595 /**
596 * Join IPv4 multicast group
597 */
598 static int join4(FileDescriptor fd, int group, int interf, int source)
599 throws IOException
600 {
601 return joinOrDrop4(true, fd, group, interf, source);
602 }
603
604 /**
605 * Drop membership of IPv4 multicast group
606 */
607 static void drop4(FileDescriptor fd, int group, int interf, int source)
608 throws IOException
609 {
610 joinOrDrop4(false, fd, group, interf, source);
611 }
612
613 private static native int joinOrDrop4(boolean join, FileDescriptor fd, int group, int interf, int source)
614 throws IOException;
615
616 /**
617 * Block IPv4 source
618 */
619 static int block4(FileDescriptor fd, int group, int interf, int source)
620 throws IOException
621 {
622 return blockOrUnblock4(true, fd, group, interf, source);
623 }
624
625 /**
626 * Unblock IPv6 source
627 */
628 static void unblock4(FileDescriptor fd, int group, int interf, int source)
629 throws IOException
630 {
631 blockOrUnblock4(false, fd, group, interf, source);
632 }
633
634 private static native int blockOrUnblock4(boolean block, FileDescriptor fd, int group,
635 int interf, int source)
636 throws IOException;
637
638 /**
639 * Join IPv6 multicast group
640 */
641 static int join6(FileDescriptor fd, byte[] group, int index, byte[] source)
642 throws IOException
643 {
644 return joinOrDrop6(true, fd, group, index, source);
645 }
646
647 /**
648 * Drop membership of IPv6 multicast group
649 */
650 static void drop6(FileDescriptor fd, byte[] group, int index, byte[] source)
651 throws IOException
652 {
653 joinOrDrop6(false, fd, group, index, source);
654 }
655
656 private static native int joinOrDrop6(boolean join, FileDescriptor fd, byte[] group, int index, byte[] source)
657 throws IOException;
658
659 /**
660 * Block IPv6 source
661 */
662 static int block6(FileDescriptor fd, byte[] group, int index, byte[] source)
663 throws IOException
664 {
665 return blockOrUnblock6(true, fd, group, index, source);
666 }
667
668 /**
669 * Unblock IPv6 source
670 */
671 static void unblock6(FileDescriptor fd, byte[] group, int index, byte[] source)
672 throws IOException
673 {
674 blockOrUnblock6(false, fd, group, index, source);
675 }
676
677 static native int blockOrUnblock6(boolean block, FileDescriptor fd, byte[] group, int index, byte[] source)
678 throws IOException;
679
680 static native void setInterface4(FileDescriptor fd, int interf) throws IOException;
681
682 static native int getInterface4(FileDescriptor fd) throws IOException;
683
684 static native void setInterface6(FileDescriptor fd, int index) throws IOException;
685
686 static native int getInterface6(FileDescriptor fd) throws IOException;
687
688 private static native void initIDs();
689
690 /**
691 * Event masks for the various poll system calls.
692 * They will be set platform dependent in the static initializer below.
693 */
694 public static final short POLLIN;
695 public static final short POLLOUT;
696 public static final short POLLERR;
697 public static final short POLLHUP;
698 public static final short POLLNVAL;
699 public static final short POLLCONN;
700
701 static native short pollinValue();
702 static native short polloutValue();
703 static native short pollerrValue();
704 static native short pollhupValue();
705 static native short pollnvalValue();
706 static native short pollconnValue();
707
708 static {
709 IOUtil.load();
710 initIDs();
711
712 POLLIN = pollinValue();
713 POLLOUT = polloutValue();
714 POLLERR = pollerrValue();
715 POLLHUP = pollhupValue();
716 POLLNVAL = pollnvalValue();
717 POLLCONN = pollconnValue();
718 }
719
720 static {
721 int availLevel = isExclusiveBindAvailable();
722 if (availLevel >= 0) {
723 String exclBindProp = GetPropertyAction
724 .privilegedGetProperty("sun.net.useExclusiveBind");
725 if (exclBindProp != null) {
726 exclusiveBind = exclBindProp.isEmpty() ?
727 true : Boolean.parseBoolean(exclBindProp);
728 } else if (availLevel == 1) {
729 exclusiveBind = true;
730 } else {
731 exclusiveBind = false;
732 }
733 } else {
734 exclusiveBind = false;
735 }
736
737 fastLoopback = isFastTcpLoopbackRequested();
738 }
739 }