1/*
2 * Copyright (c) 2011, 2013, 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
26package java.net;
27
28/**
29 * Choose a network interface to be the default for
30 * outgoing IPv6 traffic that does not specify a scope_id (and which needs one).
31 * We choose the first interface that is up and is (in order of preference):
32 * 1. neither loopback nor point to point
33 * 2. point to point
34 * 3. loopback
35 * 4. none.
36 * Platforms that do not require a default interface implement a dummy
37 * that returns null.
38 */
39
40import java.util.Enumeration;
41import java.io.IOException;
42
43class DefaultInterface {
44
45    private static final NetworkInterface defaultInterface =
46        chooseDefaultInterface();
47
48    static NetworkInterface getDefault() {
49        return defaultInterface;
50    }
51
52    /**
53     * Choose a default interface. This method returns the first interface that
54     * is both "up" and supports multicast. This method chooses an interface in
55     * order of preference:
56     * 1. neither loopback nor point to point
57     *    ( prefer interfaces with dual IP support )
58     * 2. point to point
59     * 3. loopback
60     *
61     * @return  the chosen interface or {@code null} if there isn't a suitable
62     *          default
63     */
64    private static NetworkInterface chooseDefaultInterface() {
65        Enumeration<NetworkInterface> nifs;
66
67        try {
68           nifs = NetworkInterface.getNetworkInterfaces();
69        } catch (IOException ignore) {
70            // unable to enumerate network interfaces
71            return null;
72        }
73
74        NetworkInterface preferred = null;
75        NetworkInterface ppp = null;
76        NetworkInterface loopback = null;
77
78        while (nifs.hasMoreElements()) {
79            NetworkInterface ni = nifs.nextElement();
80            try {
81                if (!ni.isUp() || !ni.supportsMulticast())
82                    continue;
83
84                boolean ip4 = false, ip6 = false;
85                Enumeration<InetAddress> addrs = ni.getInetAddresses();
86                while (addrs.hasMoreElements()) {
87                    InetAddress addr = addrs.nextElement();
88                    if (!addr.isAnyLocalAddress()) {
89                        if (addr instanceof Inet4Address) {
90                            ip4 = true;
91                        } else if (addr instanceof Inet6Address) {
92                            ip6 = true;
93                        }
94                    }
95                }
96
97                boolean isLoopback = ni.isLoopback();
98                boolean isPPP = ni.isPointToPoint();
99                if (!isLoopback && !isPPP) {
100                    // found an interface that is not the loopback or a
101                    // point-to-point interface
102                    if (preferred == null) {
103                        preferred = ni;
104                    } else if (ip4 && ip6){
105                        return ni;
106                    }
107                }
108                if (ppp == null && isPPP)
109                    ppp = ni;
110                if (loopback == null && isLoopback)
111                    loopback = ni;
112
113            } catch (IOException skip) { }
114        }
115
116        if (preferred != null) {
117            return preferred;
118        } else {
119            return (ppp != null) ? ppp : loopback;
120        }
121    }
122}
123