Loading core/java/android/net/IpReachabilityMonitor.java +47 −7 Original line number Original line Diff line number Diff line Loading @@ -75,7 +75,6 @@ public class IpReachabilityMonitor { private boolean mRunning; private boolean mRunning; final private Thread mObserverThread; final private Thread mObserverThread; // TODO: consider passing in a NetworkInterface object from the caller. public IpReachabilityMonitor(String ifName, Callback callback) throws IllegalArgumentException { public IpReachabilityMonitor(String ifName, Callback callback) throws IllegalArgumentException { mInterfaceName = ifName; mInterfaceName = ifName; int ifIndex = -1; int ifIndex = -1; Loading Loading @@ -154,6 +153,12 @@ public class IpReachabilityMonitor { } } } } private boolean stillRunning() { synchronized (mLock) { return mRunning; } } public void updateLinkProperties(LinkProperties lp) { public void updateLinkProperties(LinkProperties lp) { if (!mInterfaceName.equals(lp.getInterfaceName())) { if (!mInterfaceName.equals(lp.getInterfaceName())) { // TODO: figure out how to cope with interface changes. // TODO: figure out how to cope with interface changes. Loading Loading @@ -204,6 +209,47 @@ public class IpReachabilityMonitor { } } } } public void probeAll() { Set<InetAddress> ipProbeList = new HashSet<InetAddress>(); synchronized (mLock) { ipProbeList.addAll(mIpWatchList); } for (InetAddress target : ipProbeList) { if (!stillRunning()) { break; } probeIp(target); } } private void probeIp(InetAddress ip) { // This currently does not cause neighbor probing if the target |ip| // has been confirmed reachable within the past "delay_probe_time" // seconds, i.e. within the past 5 seconds. // // TODO: replace with a transition directly to NUD_PROBE state once // kernels are updated to do so correctly. if (DBG) { Log.d(TAG, "Probing ip=" + ip.getHostAddress()); } final byte[] msg = RtNetlinkNeighborMessage.newNewNeighborMessage( 1, ip, StructNdMsg.NUD_DELAY, mInterfaceIndex, null); NetlinkSocket nlSocket = null; try { nlSocket = new NetlinkSocket(OsConstants.NETLINK_ROUTE); nlSocket.connectToKernel(); nlSocket.sendMessage(msg, 0, msg.length, 300); final NetlinkMessage response = NetlinkMessage.parse(nlSocket.recvMessage(300)); if (response != null && response instanceof NetlinkErrorMessage) { Log.e(TAG, "Error probing ip=" + response.toString()); } } catch (ErrnoException | InterruptedIOException | SocketException e) { Log.d(TAG, "Error probing ip=" + ip.getHostAddress(), e); } if (nlSocket != null) { nlSocket.close(); } } private final class NetlinkSocketObserver implements Runnable { private final class NetlinkSocketObserver implements Runnable { private static final String TAG = "NetlinkSocketObserver"; private static final String TAG = "NetlinkSocketObserver"; Loading Loading @@ -242,12 +288,6 @@ public class IpReachabilityMonitor { if (VDBG) { Log.d(TAG, "Finishing observing thread."); } if (VDBG) { Log.d(TAG, "Finishing observing thread."); } } } private boolean stillRunning() { synchronized (mLock) { return mRunning; } } private void clearNetlinkSocket() { private void clearNetlinkSocket() { if (mSocket != null) { if (mSocket != null) { mSocket.close(); mSocket.close(); Loading core/java/android/net/netlink/RtNetlinkNeighborMessage.java +65 −0 Original line number Original line Diff line number Diff line Loading @@ -21,9 +21,11 @@ import android.net.netlink.StructNdMsg; import android.net.netlink.StructNlAttr; import android.net.netlink.StructNlAttr; import android.net.netlink.StructNlMsgHdr; import android.net.netlink.StructNlMsgHdr; import android.net.netlink.NetlinkMessage; import android.net.netlink.NetlinkMessage; import android.system.OsConstants; import android.util.Log; import android.util.Log; import java.net.InetAddress; import java.net.InetAddress; import java.net.Inet6Address; import java.nio.ByteBuffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.ByteOrder; Loading Loading @@ -131,6 +133,34 @@ public class RtNetlinkNeighborMessage extends NetlinkMessage { return bytes; return bytes; } } /** * A convenience method to create an RTM_NEWNEIGH message, to modify * the kernel's state information for a specific neighbor. */ public static byte[] newNewNeighborMessage( int seqNo, InetAddress ip, short nudState, int ifIndex, byte[] llAddr) { final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr(); nlmsghdr.nlmsg_type = NetlinkConstants.RTM_NEWNEIGH; nlmsghdr.nlmsg_flags = StructNlMsgHdr.NLM_F_REQUEST | StructNlMsgHdr.NLM_F_REPLACE; nlmsghdr.nlmsg_seq = seqNo; final RtNetlinkNeighborMessage msg = new RtNetlinkNeighborMessage(nlmsghdr); msg.mNdmsg = new StructNdMsg(); msg.mNdmsg.ndm_family = (byte) ((ip instanceof Inet6Address) ? OsConstants.AF_INET6 : OsConstants.AF_INET); msg.mNdmsg.ndm_ifindex = ifIndex; msg.mNdmsg.ndm_state = nudState; msg.mDestination = ip; msg.mLinkLayerAddr = llAddr; // might be null final byte[] bytes = new byte[msg.getRequiredSpace()]; nlmsghdr.nlmsg_len = bytes.length; final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); byteBuffer.order(ByteOrder.nativeOrder()); msg.pack(byteBuffer); return bytes; } private StructNdMsg mNdmsg; private StructNdMsg mNdmsg; private InetAddress mDestination; private InetAddress mDestination; private byte[] mLinkLayerAddr; private byte[] mLinkLayerAddr; Loading Loading @@ -166,6 +196,41 @@ public class RtNetlinkNeighborMessage extends NetlinkMessage { return mCacheInfo; return mCacheInfo; } } public int getRequiredSpace() { int spaceRequired = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE; if (mDestination != null) { spaceRequired += NetlinkConstants.alignedLengthOf( StructNlAttr.NLA_HEADERLEN + mDestination.getAddress().length); } if (mLinkLayerAddr != null) { spaceRequired += NetlinkConstants.alignedLengthOf( StructNlAttr.NLA_HEADERLEN + mLinkLayerAddr.length); } // Currently we don't write messages with NDA_PROBES nor NDA_CACHEINFO // attributes appended. Fix later, if necessary. return spaceRequired; } private static void packNlAttr(short nlType, byte[] nlValue, ByteBuffer byteBuffer) { final StructNlAttr nlAttr = new StructNlAttr(); nlAttr.nla_type = nlType; nlAttr.nla_value = nlValue; nlAttr.nla_len = (short) (StructNlAttr.NLA_HEADERLEN + nlAttr.nla_value.length); nlAttr.pack(byteBuffer); } public void pack(ByteBuffer byteBuffer) { getHeader().pack(byteBuffer) ; mNdmsg.pack(byteBuffer); if (mDestination != null) { packNlAttr(NDA_DST, mDestination.getAddress(), byteBuffer); } if (mLinkLayerAddr != null) { packNlAttr(NDA_LLADDR, mLinkLayerAddr, byteBuffer); } } @Override @Override public String toString() { public String toString() { final String ipLiteral = (mDestination == null) ? "" : mDestination.getHostAddress(); final String ipLiteral = (mDestination == null) ? "" : mDestination.getHostAddress(); Loading core/java/android/net/netlink/StructNdMsg.java +1 −4 Original line number Original line Diff line number Diff line Loading @@ -123,9 +123,7 @@ public class StructNdMsg { ndm_family = (byte) OsConstants.AF_UNSPEC; ndm_family = (byte) OsConstants.AF_UNSPEC; } } public boolean pack(ByteBuffer byteBuffer) { public void pack(ByteBuffer byteBuffer) { if (!hasAvailableSpace(byteBuffer)) { return false; } // The ByteOrder must have already been set by the caller. In most // The ByteOrder must have already been set by the caller. In most // cases ByteOrder.nativeOrder() is correct, with the exception // cases ByteOrder.nativeOrder() is correct, with the exception // of usage within unittests. // of usage within unittests. Loading @@ -136,7 +134,6 @@ public class StructNdMsg { byteBuffer.putShort(ndm_state); byteBuffer.putShort(ndm_state); byteBuffer.put(ndm_flags); byteBuffer.put(ndm_flags); byteBuffer.put(ndm_type); byteBuffer.put(ndm_type); return true; } } public boolean nudConnected() { public boolean nudConnected() { Loading core/java/android/net/netlink/StructNlAttr.java +8 −0 Original line number Original line Diff line number Diff line Loading @@ -116,6 +116,14 @@ public class StructNlAttr { } } } } public void pack(ByteBuffer byteBuffer) { final int originalPosition = byteBuffer.position(); byteBuffer.putShort(nla_len); byteBuffer.putShort(nla_type); byteBuffer.put(nla_value); byteBuffer.position(originalPosition + getAlignedLength()); } @Override @Override public String toString() { public String toString() { return "StructNlAttr{ " return "StructNlAttr{ " Loading core/java/android/net/netlink/StructNlMsgErr.java +1 −4 Original line number Original line Diff line number Diff line Loading @@ -57,9 +57,7 @@ public class StructNlMsgErr { msg = null; msg = null; } } public boolean pack(ByteBuffer byteBuffer) { public void pack(ByteBuffer byteBuffer) { if (!hasAvailableSpace(byteBuffer)) { return false; } // The ByteOrder must have already been set by the caller. In most // The ByteOrder must have already been set by the caller. In most // cases ByteOrder.nativeOrder() is correct, with the possible // cases ByteOrder.nativeOrder() is correct, with the possible // exception of usage within unittests. // exception of usage within unittests. Loading @@ -67,7 +65,6 @@ public class StructNlMsgErr { if (msg != null) { if (msg != null) { msg.pack(byteBuffer); msg.pack(byteBuffer); } } return true; } } @Override @Override Loading Loading
core/java/android/net/IpReachabilityMonitor.java +47 −7 Original line number Original line Diff line number Diff line Loading @@ -75,7 +75,6 @@ public class IpReachabilityMonitor { private boolean mRunning; private boolean mRunning; final private Thread mObserverThread; final private Thread mObserverThread; // TODO: consider passing in a NetworkInterface object from the caller. public IpReachabilityMonitor(String ifName, Callback callback) throws IllegalArgumentException { public IpReachabilityMonitor(String ifName, Callback callback) throws IllegalArgumentException { mInterfaceName = ifName; mInterfaceName = ifName; int ifIndex = -1; int ifIndex = -1; Loading Loading @@ -154,6 +153,12 @@ public class IpReachabilityMonitor { } } } } private boolean stillRunning() { synchronized (mLock) { return mRunning; } } public void updateLinkProperties(LinkProperties lp) { public void updateLinkProperties(LinkProperties lp) { if (!mInterfaceName.equals(lp.getInterfaceName())) { if (!mInterfaceName.equals(lp.getInterfaceName())) { // TODO: figure out how to cope with interface changes. // TODO: figure out how to cope with interface changes. Loading Loading @@ -204,6 +209,47 @@ public class IpReachabilityMonitor { } } } } public void probeAll() { Set<InetAddress> ipProbeList = new HashSet<InetAddress>(); synchronized (mLock) { ipProbeList.addAll(mIpWatchList); } for (InetAddress target : ipProbeList) { if (!stillRunning()) { break; } probeIp(target); } } private void probeIp(InetAddress ip) { // This currently does not cause neighbor probing if the target |ip| // has been confirmed reachable within the past "delay_probe_time" // seconds, i.e. within the past 5 seconds. // // TODO: replace with a transition directly to NUD_PROBE state once // kernels are updated to do so correctly. if (DBG) { Log.d(TAG, "Probing ip=" + ip.getHostAddress()); } final byte[] msg = RtNetlinkNeighborMessage.newNewNeighborMessage( 1, ip, StructNdMsg.NUD_DELAY, mInterfaceIndex, null); NetlinkSocket nlSocket = null; try { nlSocket = new NetlinkSocket(OsConstants.NETLINK_ROUTE); nlSocket.connectToKernel(); nlSocket.sendMessage(msg, 0, msg.length, 300); final NetlinkMessage response = NetlinkMessage.parse(nlSocket.recvMessage(300)); if (response != null && response instanceof NetlinkErrorMessage) { Log.e(TAG, "Error probing ip=" + response.toString()); } } catch (ErrnoException | InterruptedIOException | SocketException e) { Log.d(TAG, "Error probing ip=" + ip.getHostAddress(), e); } if (nlSocket != null) { nlSocket.close(); } } private final class NetlinkSocketObserver implements Runnable { private final class NetlinkSocketObserver implements Runnable { private static final String TAG = "NetlinkSocketObserver"; private static final String TAG = "NetlinkSocketObserver"; Loading Loading @@ -242,12 +288,6 @@ public class IpReachabilityMonitor { if (VDBG) { Log.d(TAG, "Finishing observing thread."); } if (VDBG) { Log.d(TAG, "Finishing observing thread."); } } } private boolean stillRunning() { synchronized (mLock) { return mRunning; } } private void clearNetlinkSocket() { private void clearNetlinkSocket() { if (mSocket != null) { if (mSocket != null) { mSocket.close(); mSocket.close(); Loading
core/java/android/net/netlink/RtNetlinkNeighborMessage.java +65 −0 Original line number Original line Diff line number Diff line Loading @@ -21,9 +21,11 @@ import android.net.netlink.StructNdMsg; import android.net.netlink.StructNlAttr; import android.net.netlink.StructNlAttr; import android.net.netlink.StructNlMsgHdr; import android.net.netlink.StructNlMsgHdr; import android.net.netlink.NetlinkMessage; import android.net.netlink.NetlinkMessage; import android.system.OsConstants; import android.util.Log; import android.util.Log; import java.net.InetAddress; import java.net.InetAddress; import java.net.Inet6Address; import java.nio.ByteBuffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.ByteOrder; Loading Loading @@ -131,6 +133,34 @@ public class RtNetlinkNeighborMessage extends NetlinkMessage { return bytes; return bytes; } } /** * A convenience method to create an RTM_NEWNEIGH message, to modify * the kernel's state information for a specific neighbor. */ public static byte[] newNewNeighborMessage( int seqNo, InetAddress ip, short nudState, int ifIndex, byte[] llAddr) { final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr(); nlmsghdr.nlmsg_type = NetlinkConstants.RTM_NEWNEIGH; nlmsghdr.nlmsg_flags = StructNlMsgHdr.NLM_F_REQUEST | StructNlMsgHdr.NLM_F_REPLACE; nlmsghdr.nlmsg_seq = seqNo; final RtNetlinkNeighborMessage msg = new RtNetlinkNeighborMessage(nlmsghdr); msg.mNdmsg = new StructNdMsg(); msg.mNdmsg.ndm_family = (byte) ((ip instanceof Inet6Address) ? OsConstants.AF_INET6 : OsConstants.AF_INET); msg.mNdmsg.ndm_ifindex = ifIndex; msg.mNdmsg.ndm_state = nudState; msg.mDestination = ip; msg.mLinkLayerAddr = llAddr; // might be null final byte[] bytes = new byte[msg.getRequiredSpace()]; nlmsghdr.nlmsg_len = bytes.length; final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); byteBuffer.order(ByteOrder.nativeOrder()); msg.pack(byteBuffer); return bytes; } private StructNdMsg mNdmsg; private StructNdMsg mNdmsg; private InetAddress mDestination; private InetAddress mDestination; private byte[] mLinkLayerAddr; private byte[] mLinkLayerAddr; Loading Loading @@ -166,6 +196,41 @@ public class RtNetlinkNeighborMessage extends NetlinkMessage { return mCacheInfo; return mCacheInfo; } } public int getRequiredSpace() { int spaceRequired = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE; if (mDestination != null) { spaceRequired += NetlinkConstants.alignedLengthOf( StructNlAttr.NLA_HEADERLEN + mDestination.getAddress().length); } if (mLinkLayerAddr != null) { spaceRequired += NetlinkConstants.alignedLengthOf( StructNlAttr.NLA_HEADERLEN + mLinkLayerAddr.length); } // Currently we don't write messages with NDA_PROBES nor NDA_CACHEINFO // attributes appended. Fix later, if necessary. return spaceRequired; } private static void packNlAttr(short nlType, byte[] nlValue, ByteBuffer byteBuffer) { final StructNlAttr nlAttr = new StructNlAttr(); nlAttr.nla_type = nlType; nlAttr.nla_value = nlValue; nlAttr.nla_len = (short) (StructNlAttr.NLA_HEADERLEN + nlAttr.nla_value.length); nlAttr.pack(byteBuffer); } public void pack(ByteBuffer byteBuffer) { getHeader().pack(byteBuffer) ; mNdmsg.pack(byteBuffer); if (mDestination != null) { packNlAttr(NDA_DST, mDestination.getAddress(), byteBuffer); } if (mLinkLayerAddr != null) { packNlAttr(NDA_LLADDR, mLinkLayerAddr, byteBuffer); } } @Override @Override public String toString() { public String toString() { final String ipLiteral = (mDestination == null) ? "" : mDestination.getHostAddress(); final String ipLiteral = (mDestination == null) ? "" : mDestination.getHostAddress(); Loading
core/java/android/net/netlink/StructNdMsg.java +1 −4 Original line number Original line Diff line number Diff line Loading @@ -123,9 +123,7 @@ public class StructNdMsg { ndm_family = (byte) OsConstants.AF_UNSPEC; ndm_family = (byte) OsConstants.AF_UNSPEC; } } public boolean pack(ByteBuffer byteBuffer) { public void pack(ByteBuffer byteBuffer) { if (!hasAvailableSpace(byteBuffer)) { return false; } // The ByteOrder must have already been set by the caller. In most // The ByteOrder must have already been set by the caller. In most // cases ByteOrder.nativeOrder() is correct, with the exception // cases ByteOrder.nativeOrder() is correct, with the exception // of usage within unittests. // of usage within unittests. Loading @@ -136,7 +134,6 @@ public class StructNdMsg { byteBuffer.putShort(ndm_state); byteBuffer.putShort(ndm_state); byteBuffer.put(ndm_flags); byteBuffer.put(ndm_flags); byteBuffer.put(ndm_type); byteBuffer.put(ndm_type); return true; } } public boolean nudConnected() { public boolean nudConnected() { Loading
core/java/android/net/netlink/StructNlAttr.java +8 −0 Original line number Original line Diff line number Diff line Loading @@ -116,6 +116,14 @@ public class StructNlAttr { } } } } public void pack(ByteBuffer byteBuffer) { final int originalPosition = byteBuffer.position(); byteBuffer.putShort(nla_len); byteBuffer.putShort(nla_type); byteBuffer.put(nla_value); byteBuffer.position(originalPosition + getAlignedLength()); } @Override @Override public String toString() { public String toString() { return "StructNlAttr{ " return "StructNlAttr{ " Loading
core/java/android/net/netlink/StructNlMsgErr.java +1 −4 Original line number Original line Diff line number Diff line Loading @@ -57,9 +57,7 @@ public class StructNlMsgErr { msg = null; msg = null; } } public boolean pack(ByteBuffer byteBuffer) { public void pack(ByteBuffer byteBuffer) { if (!hasAvailableSpace(byteBuffer)) { return false; } // The ByteOrder must have already been set by the caller. In most // The ByteOrder must have already been set by the caller. In most // cases ByteOrder.nativeOrder() is correct, with the possible // cases ByteOrder.nativeOrder() is correct, with the possible // exception of usage within unittests. // exception of usage within unittests. Loading @@ -67,7 +65,6 @@ public class StructNlMsgErr { if (msg != null) { if (msg != null) { msg.pack(byteBuffer); msg.pack(byteBuffer); } } return true; } } @Override @Override Loading