• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 only, as
8  * published by the Free Software Foundation.  Oracle designates this
9  * particular file as subject to the "Classpath" exception as provided
10  * by Oracle in the LICENSE file that accompanied this code.
11  *
12  * This code is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15  * version 2 for more details (a copy is included in the LICENSE file that
16  * accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License version
19  * 2 along with this work; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23  * or visit www.oracle.com if you need additional information or have any
24  * questions.
25  */
26 
27 package sun.nio.ch;
28 
29 import dalvik.system.BlockGuard;
30 
31 import java.io.*;
32 import java.net.*;
33 import java.nio.channels.*;
34 import java.util.*;
35 import java.security.AccessController;
36 import java.security.PrivilegedAction;
37 import java.security.PrivilegedExceptionAction;
38 
39 
40 class Net {                                             // package-private
41 
Net()42     private Net() { }
43 
44     // unspecified protocol family
45     static final ProtocolFamily UNSPEC = new ProtocolFamily() {
46         public String name() {
47             return "UNSPEC";
48         }
49     };
50 
51     // Value of jdk.net.revealLocalAddress
52     private static boolean revealLocalAddress;
53 
54     // True if jdk.net.revealLocalAddress had been read
55     private static volatile boolean propRevealLocalAddress;
56 
57     // set to true if exclusive binding is on for Windows
58     private static final boolean exclusiveBind;
59 
60     static {
61         int availLevel = isExclusiveBindAvailable();
62         if (availLevel >= 0) {
63             String exclBindProp =
64                 java.security.AccessController.doPrivileged(
65                       new PrivilegedAction<String>() {
66                           @Override
67                         public String run() {
68                             return System.getProperty(
69                                     "sun.net.useExclusiveBind");
70                         }
71                     });
72             if (exclBindProp != null) {
73                 exclusiveBind = exclBindProp.length() == 0 ?
74                         true : Boolean.parseBoolean(exclBindProp);
75             } else if (availLevel == 1) {
76                 exclusiveBind = true;
77             } else {
78                 exclusiveBind = false;
79             }
80         } else {
81             exclusiveBind = false;
82         }
83     }
84 
85     // -- Miscellaneous utilities --
86 
87     private static volatile boolean checkedIPv6 = false;
88     private static volatile boolean isIPv6Available;
89 
90     /**
91      * Tells whether dual-IPv4/IPv6 sockets should be used.
92      */
isIPv6Available()93     static boolean isIPv6Available() {
94         if (!checkedIPv6) {
95             isIPv6Available = isIPv6Available0();
96             checkedIPv6 = true;
97         }
98         return isIPv6Available;
99     }
100 
101     /**
102      * Returns true if exclusive binding is on
103      */
useExclusiveBind()104     static boolean useExclusiveBind() {
105         return exclusiveBind;
106     }
107 
108     /**
109      * Tells whether IPv6 sockets can join IPv4 multicast groups
110      */
canIPv6SocketJoinIPv4Group()111     static boolean canIPv6SocketJoinIPv4Group() {
112         return canIPv6SocketJoinIPv4Group0();
113     }
114 
115     /**
116      * Tells whether {@link #join6} can be used to join an IPv4
117      * multicast group (IPv4 group as IPv4-mapped IPv6 address)
118      */
canJoin6WithIPv4Group()119     static boolean canJoin6WithIPv4Group() {
120         return canJoin6WithIPv4Group0();
121     }
122 
checkAddress(SocketAddress sa)123     static InetSocketAddress checkAddress(SocketAddress sa) {
124         if (sa == null)
125             // ----- BEGIN android -----
126             //throw new NullPointerException();
127             throw new IllegalArgumentException("sa == null");
128             // ----- END android -----
129 
130         if (!(sa instanceof InetSocketAddress))
131             throw new UnsupportedAddressTypeException(); // ## needs arg
132         InetSocketAddress isa = (InetSocketAddress)sa;
133         if (isa.isUnresolved())
134             throw new UnresolvedAddressException(); // ## needs arg
135         InetAddress addr = isa.getAddress();
136         if (!(addr instanceof Inet4Address || addr instanceof Inet6Address))
137             throw new IllegalArgumentException("Invalid address type");
138         return isa;
139     }
140 
asInetSocketAddress(SocketAddress sa)141     static InetSocketAddress asInetSocketAddress(SocketAddress sa) {
142         if (!(sa instanceof InetSocketAddress))
143             throw new UnsupportedAddressTypeException();
144         return (InetSocketAddress)sa;
145     }
146 
translateToSocketException(Exception x)147     static void translateToSocketException(Exception x)
148         throws SocketException
149     {
150         if (x instanceof SocketException)
151             throw (SocketException)x;
152         Exception nx = x;
153         if (x instanceof ClosedChannelException)
154             nx = new SocketException("Socket is closed");
155         else if (x instanceof NotYetConnectedException)
156             nx = new SocketException("Socket is not connected");
157         else if (x instanceof AlreadyBoundException)
158             nx = new SocketException("Already bound");
159         else if (x instanceof NotYetBoundException)
160             nx = new SocketException("Socket is not bound yet");
161         else if (x instanceof UnsupportedAddressTypeException)
162             nx = new SocketException("Unsupported address type");
163         else if (x instanceof UnresolvedAddressException) {
164             nx = new SocketException("Unresolved address");
165         } else if (x instanceof AlreadyConnectedException) {
166             // Android added.
167             nx = new SocketException("Already connected");
168         }
169         if (nx != x)
170             nx.initCause(x);
171 
172         if (nx instanceof SocketException)
173             throw (SocketException)nx;
174         else if (nx instanceof RuntimeException)
175             throw (RuntimeException)nx;
176         else
177             throw new Error("Untranslated exception", nx);
178     }
179 
translateException(Exception x, boolean unknownHostForUnresolved)180     static void translateException(Exception x,
181                                    boolean unknownHostForUnresolved)
182         throws IOException
183     {
184         if (x instanceof IOException)
185             throw (IOException)x;
186         // Throw UnknownHostException from here since it cannot
187         // be thrown as a SocketException
188         if (unknownHostForUnresolved &&
189             (x instanceof UnresolvedAddressException))
190         {
191              throw new UnknownHostException();
192         }
193         translateToSocketException(x);
194     }
195 
translateException(Exception x)196     static void translateException(Exception x)
197         throws IOException
198     {
199         translateException(x, false);
200     }
201 
202     /**
203      * Returns the local address after performing a SecurityManager#checkConnect.
204      */
getRevealedLocalAddress(InetSocketAddress addr)205     static InetSocketAddress getRevealedLocalAddress(InetSocketAddress addr) {
206         SecurityManager sm = System.getSecurityManager();
207         if (addr == null || sm == null)
208             return addr;
209 
210         if (!getRevealLocalAddress()) {
211             // Return loopback address only if security check fails
212             try{
213                 sm.checkConnect(addr.getAddress().getHostAddress(), -1);
214                 //Security check passed
215             } catch (SecurityException e) {
216                 //Return loopback address
217                 addr = getLoopbackAddress(addr.getPort());
218             }
219         }
220         return addr;
221     }
222 
getRevealedLocalAddressAsString(InetSocketAddress addr)223     static String getRevealedLocalAddressAsString(InetSocketAddress addr) {
224         if (!getRevealLocalAddress() && System.getSecurityManager() != null)
225             addr = getLoopbackAddress(addr.getPort());
226         return addr.toString();
227     }
228 
getRevealLocalAddress()229     private static boolean getRevealLocalAddress() {
230         if (!propRevealLocalAddress) {
231             try {
232                 revealLocalAddress = Boolean.parseBoolean(
233                       AccessController.doPrivileged(
234                           new PrivilegedExceptionAction<String>() {
235                               public String run() {
236                                   return System.getProperty(
237                                       "jdk.net.revealLocalAddress");
238                               }
239                           }));
240 
241             } catch (Exception e) {
242                 // revealLocalAddress is false
243             }
244             propRevealLocalAddress = true;
245         }
246         return revealLocalAddress;
247     }
248 
getLoopbackAddress(int port)249     private static InetSocketAddress getLoopbackAddress(int port) {
250         return new InetSocketAddress(InetAddress.getLoopbackAddress(),
251                                      port);
252     }
253 
254     /**
255      * Returns any IPv4 address of the given network interface, or
256      * null if the interface does not have any IPv4 addresses.
257      */
anyInet4Address(final NetworkInterface interf)258     static Inet4Address anyInet4Address(final NetworkInterface interf) {
259         return AccessController.doPrivileged(new PrivilegedAction<Inet4Address>() {
260             public Inet4Address run() {
261                 Enumeration<InetAddress> addrs = interf.getInetAddresses();
262                 while (addrs.hasMoreElements()) {
263                     InetAddress addr = addrs.nextElement();
264                     if (addr instanceof Inet4Address) {
265                         return (Inet4Address)addr;
266                     }
267                 }
268                 return null;
269             }
270         });
271     }
272 
273     /**
274      * Returns an IPv4 address as an int.
275      */
276     static int inet4AsInt(InetAddress ia) {
277         if (ia instanceof Inet4Address) {
278             byte[] addr = ia.getAddress();
279             int address  = addr[3] & 0xFF;
280             address |= ((addr[2] << 8) & 0xFF00);
281             address |= ((addr[1] << 16) & 0xFF0000);
282             address |= ((addr[0] << 24) & 0xFF000000);
283             return address;
284         }
285         throw new AssertionError("Should not reach here");
286     }
287 
288     /**
289      * Returns an InetAddress from the given IPv4 address
290      * represented as an int.
291      */
292     static InetAddress inet4FromInt(int address) {
293         byte[] addr = new byte[4];
294         addr[0] = (byte) ((address >>> 24) & 0xFF);
295         addr[1] = (byte) ((address >>> 16) & 0xFF);
296         addr[2] = (byte) ((address >>> 8) & 0xFF);
297         addr[3] = (byte) (address & 0xFF);
298         try {
299             return InetAddress.getByAddress(addr);
300         } catch (UnknownHostException uhe) {
301             throw new AssertionError("Should not reach here");
302         }
303     }
304 
305     /**
306      * Returns an IPv6 address as a byte array
307      */
308     static byte[] inet6AsByteArray(InetAddress ia) {
309         if (ia instanceof Inet6Address) {
310             return ia.getAddress();
311         }
312 
313         // need to construct IPv4-mapped address
314         if (ia instanceof Inet4Address) {
315             byte[] ip4address = ia.getAddress();
316             byte[] address = new byte[16];
317             address[10] = (byte)0xff;
318             address[11] = (byte)0xff;
319             address[12] = ip4address[0];
320             address[13] = ip4address[1];
321             address[14] = ip4address[2];
322             address[15] = ip4address[3];
323             return address;
324         }
325 
326         throw new AssertionError("Should not reach here");
327     }
328 
329     // -- Socket options
330 
331     static void setSocketOption(FileDescriptor fd, ProtocolFamily family,
332                                 SocketOption<?> name, Object value)
333         throws IOException
334     {
335         if (value == null)
336             throw new IllegalArgumentException("Invalid option value");
337 
338         // only simple values supported by this method
339         Class<?> type = name.type();
340         if (type != Integer.class && type != Boolean.class)
341             throw new AssertionError("Should not reach here");
342 
343         // special handling
344         if (name == StandardSocketOptions.SO_RCVBUF ||
345             name == StandardSocketOptions.SO_SNDBUF)
346         {
347             int i = ((Integer)value).intValue();
348             if (i < 0)
349                 throw new IllegalArgumentException("Invalid send/receive buffer size");
350         }
351         if (name == StandardSocketOptions.SO_LINGER) {
352             int i = ((Integer)value).intValue();
353             if (i < 0)
354                 value = Integer.valueOf(-1);
355             if (i > 65535)
356                 value = Integer.valueOf(65535);
357         }
358         if (name == StandardSocketOptions.IP_TOS) {
359             int i = ((Integer)value).intValue();
360             if (i < 0 || i > 255)
361                 throw new IllegalArgumentException("Invalid IP_TOS value");
362         }
363         if (name == StandardSocketOptions.IP_MULTICAST_TTL) {
364             int i = ((Integer)value).intValue();
365             if (i < 0 || i > 255)
366                 throw new IllegalArgumentException("Invalid TTL/hop value");
367         }
368 
369         // map option name to platform level/name
370         OptionKey key = SocketOptionRegistry.findOption(name, family);
371         if (key == null)
372             throw new AssertionError("Option not found");
373 
374         int arg;
375         if (type == Integer.class) {
376             arg = ((Integer)value).intValue();
377         } else {
378             boolean b = ((Boolean)value).booleanValue();
379             arg = (b) ? 1 : 0;
380         }
381 
382         boolean mayNeedConversion = (family == UNSPEC);
383         setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg);
384     }
385 
386     static Object getSocketOption(FileDescriptor fd, ProtocolFamily family,
387                                   SocketOption<?> name)
388         throws IOException
389     {
390         Class<?> type = name.type();
391 
392         // only simple values supported by this method
393         if (type != Integer.class && type != Boolean.class)
394             throw new AssertionError("Should not reach here");
395 
396         // map option name to platform level/name
397         OptionKey key = SocketOptionRegistry.findOption(name, family);
398         if (key == null)
399             throw new AssertionError("Option not found");
400 
401         boolean mayNeedConversion = (family == UNSPEC);
402         int value = getIntOption0(fd, mayNeedConversion, key.level(), key.name());
403 
404         if (type == Integer.class) {
405             return Integer.valueOf(value);
406         } else {
407             return (value == 0) ? Boolean.FALSE : Boolean.TRUE;
408         }
409     }
410 
411     // -- Socket operations --
412 
413     private static native boolean isIPv6Available0();
414 
415     /*
416      * Returns 1 for Windows versions that support exclusive binding by default, 0
417      * for those that do not, and -1 for Solaris/Linux/Mac OS
418      */
419     private static native int isExclusiveBindAvailable();
420 
421     private static native boolean canIPv6SocketJoinIPv4Group0();
422 
423     private static native boolean canJoin6WithIPv4Group0();
424 
425     static FileDescriptor socket(boolean stream) throws IOException {
426         return socket(UNSPEC, stream);
427     }
428 
429     static FileDescriptor socket(ProtocolFamily family, boolean stream)
430         throws IOException {
431         boolean preferIPv6 = isIPv6Available() &&
432             (family != StandardProtocolFamily.INET);
433         return IOUtil.newFD(socket0(preferIPv6, stream, false));
434     }
435 
436     static FileDescriptor serverSocket(boolean stream) {
437         return IOUtil.newFD(socket0(isIPv6Available(), stream, true));
438     }
439 
440     // Due to oddities SO_REUSEADDR on windows reuse is ignored
441     private static native int socket0(boolean preferIPv6, boolean stream, boolean reuse);
442 
443     static void bind(FileDescriptor fd, InetAddress addr, int port)
444         throws IOException
445     {
446         bind(UNSPEC, fd, addr, port);
447     }
448 
449     static void bind(ProtocolFamily family, FileDescriptor fd,
450                      InetAddress addr, int port) throws IOException
451     {
452         boolean preferIPv6 = isIPv6Available() &&
453             (family != StandardProtocolFamily.INET);
454         bind0(fd, preferIPv6, exclusiveBind, addr, port);
455     }
456 
457     private static native void bind0(FileDescriptor fd, boolean preferIPv6,
458                                      boolean useExclBind, InetAddress addr,
459                                      int port)
460         throws IOException;
461 
462     static native void listen(FileDescriptor fd, int backlog) throws IOException;
463 
464     static int connect(FileDescriptor fd, InetAddress remote, int remotePort)
465         throws IOException
466     {
467         return connect(UNSPEC, fd, remote, remotePort);
468     }
469 
470     static int connect(ProtocolFamily family, FileDescriptor fd, InetAddress remote, int remotePort)
471         throws IOException
472     {
473         BlockGuard.getThreadPolicy().onNetwork();
474 
475         boolean preferIPv6 = isIPv6Available() &&
476             (family != StandardProtocolFamily.INET);
477         return connect0(preferIPv6, fd, remote, remotePort);
478     }
479 
480     private static native int connect0(boolean preferIPv6,
481                                        FileDescriptor fd,
482                                        InetAddress remote,
483                                        int remotePort)
484         throws IOException;
485 
486 
487     public final static int SHUT_RD = 0;
488     public final static int SHUT_WR = 1;
489     public final static int SHUT_RDWR = 2;
490 
491     static native void shutdown(FileDescriptor fd, int how) throws IOException;
492 
493     private static native int localPort(FileDescriptor fd)
494         throws IOException;
495 
496     private static native InetAddress localInetAddress(FileDescriptor fd)
497         throws IOException;
498 
499     static InetSocketAddress localAddress(FileDescriptor fd)
500         throws IOException
501     {
502         return new InetSocketAddress(localInetAddress(fd), localPort(fd));
503     }
504 
505     private static native int remotePort(FileDescriptor fd)
506         throws IOException;
507 
508     private static native InetAddress remoteInetAddress(FileDescriptor fd)
509         throws IOException;
510 
511     static InetSocketAddress remoteAddress(FileDescriptor fd)
512         throws IOException
513     {
514         return new InetSocketAddress(remoteInetAddress(fd), remotePort(fd));
515     }
516 
517     private static native int getIntOption0(FileDescriptor fd, boolean mayNeedConversion,
518                                             int level, int opt)
519         throws IOException;
520 
521     private static native void setIntOption0(FileDescriptor fd, boolean mayNeedConversion,
522                                              int level, int opt, int arg)
523         throws IOException;
524 
525     // -- Multicast support --
526 
527 
528     /**
529      * Join IPv4 multicast group
530      */
531     static int join4(FileDescriptor fd, int group, int interf, int source)
532         throws IOException
533     {
534         return joinOrDrop4(true, fd, group, interf, source);
535     }
536 
537     /**
538      * Drop membership of IPv4 multicast group
539      */
540     static void drop4(FileDescriptor fd, int group, int interf, int source)
541         throws IOException
542     {
543         joinOrDrop4(false, fd, group, interf, source);
544     }
545 
546     private static native int joinOrDrop4(boolean join, FileDescriptor fd, int group, int interf, int source)
547         throws IOException;
548 
549     /**
550      * Block IPv4 source
551      */
552     static int block4(FileDescriptor fd, int group, int interf, int source)
553         throws IOException
554     {
555         return blockOrUnblock4(true, fd, group, interf, source);
556     }
557 
558     /**
559      * Unblock IPv6 source
560      */
561     static void unblock4(FileDescriptor fd, int group, int interf, int source)
562         throws IOException
563     {
564         blockOrUnblock4(false, fd, group, interf, source);
565     }
566 
567     private static native int blockOrUnblock4(boolean block, FileDescriptor fd, int group,
568                                               int interf, int source)
569         throws IOException;
570 
571     /**
572      * Join IPv6 multicast group
573      */
574     static int join6(FileDescriptor fd, byte[] group, int index, byte[] source)
575         throws IOException
576     {
577         return joinOrDrop6(true, fd, group, index, source);
578     }
579 
580     /**
581      * Drop membership of IPv6 multicast group
582      */
583     static void drop6(FileDescriptor fd, byte[] group, int index, byte[] source)
584         throws IOException
585     {
586         joinOrDrop6(false, fd, group, index, source);
587     }
588 
589     private static native int joinOrDrop6(boolean join, FileDescriptor fd, byte[] group, int index, byte[] source)
590         throws IOException;
591 
592     /**
593      * Block IPv6 source
594      */
595     static int block6(FileDescriptor fd, byte[] group, int index, byte[] source)
596         throws IOException
597     {
598         return blockOrUnblock6(true, fd, group, index, source);
599     }
600 
601     /**
602      * Unblock IPv6 source
603      */
604     static void unblock6(FileDescriptor fd, byte[] group, int index, byte[] source)
605         throws IOException
606     {
607         blockOrUnblock6(false, fd, group, index, source);
608     }
609 
610     static native int blockOrUnblock6(boolean block, FileDescriptor fd, byte[] group, int index, byte[] source)
611         throws IOException;
612 
613     static native void setInterface4(FileDescriptor fd, int interf) throws IOException;
614 
615     static native int getInterface4(FileDescriptor fd) throws IOException;
616 
617     static native void setInterface6(FileDescriptor fd, int index) throws IOException;
618 
619     static native int getInterface6(FileDescriptor fd) throws IOException;
620 }
621