Add a method helper to create RTM_NEWADDR message in user space.
Bug: 260934173 Test: atest NetworkStaticLibTests Change-Id: I39a53a3d8b0cd10437aeed502657dd34d8b7775d
This commit is contained in:
@@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
package com.android.net.module.util.netlink;
|
package com.android.net.module.util.netlink;
|
||||||
|
|
||||||
|
import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_ACK;
|
||||||
|
import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REPLACE;
|
||||||
|
import static com.android.net.module.util.netlink.StructNlMsgHdr.NLM_F_REQUEST;
|
||||||
|
|
||||||
import android.system.OsConstants;
|
import android.system.OsConstants;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
@@ -24,8 +28,10 @@ import androidx.annotation.VisibleForTesting;
|
|||||||
|
|
||||||
import com.android.net.module.util.HexDump;
|
import com.android.net.module.util.HexDump;
|
||||||
|
|
||||||
|
import java.net.Inet6Address;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A NetlinkMessage subclass for rtnetlink address messages.
|
* A NetlinkMessage subclass for rtnetlink address messages.
|
||||||
@@ -145,6 +151,47 @@ public class RtNetlinkAddressMessage extends NetlinkMessage {
|
|||||||
flags.pack(byteBuffer);
|
flags.pack(byteBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A convenience method to create an RTM_NEWADDR message.
|
||||||
|
*/
|
||||||
|
public static byte[] newRtmNewAddressMessage(int seqNo, final InetAddress ip, short prefixlen,
|
||||||
|
byte flags, byte scope, int ifIndex, long preferred, long valid) {
|
||||||
|
final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr();
|
||||||
|
nlmsghdr.nlmsg_type = NetlinkConstants.RTM_NEWADDR;
|
||||||
|
nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_REPLACE;
|
||||||
|
nlmsghdr.nlmsg_seq = seqNo;
|
||||||
|
|
||||||
|
final RtNetlinkAddressMessage msg = new RtNetlinkAddressMessage(nlmsghdr);
|
||||||
|
final byte family =
|
||||||
|
(byte) ((ip instanceof Inet6Address) ? OsConstants.AF_INET6 : OsConstants.AF_INET);
|
||||||
|
msg.mIfaddrmsg = new StructIfaddrMsg(family, prefixlen, flags, scope, ifIndex);
|
||||||
|
msg.mIpAddress = ip;
|
||||||
|
msg.mIfacacheInfo = new StructIfacacheInfo(preferred, valid, 0 /* cstamp */,
|
||||||
|
0 /* tstamp */);
|
||||||
|
msg.mFlags = (int) (flags & 0xFF);
|
||||||
|
|
||||||
|
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 int getRequiredSpace() {
|
||||||
|
int spaceRequired = StructNlMsgHdr.STRUCT_SIZE + StructIfaddrMsg.STRUCT_SIZE;
|
||||||
|
if (mIpAddress != null) {
|
||||||
|
spaceRequired += NetlinkConstants.alignedLengthOf(
|
||||||
|
StructNlAttr.NLA_HEADERLEN + mIpAddress.getAddress().length);
|
||||||
|
}
|
||||||
|
if (mIfacacheInfo != null) {
|
||||||
|
spaceRequired += NetlinkConstants.alignedLengthOf(
|
||||||
|
StructNlAttr.NLA_HEADERLEN + StructIfacacheInfo.STRUCT_SIZE);
|
||||||
|
}
|
||||||
|
spaceRequired += StructNlAttr.NLA_HEADERLEN + 4; // IFA_FLAGS "u32" attr
|
||||||
|
return spaceRequired;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "RtNetlinkAddressMessage{ "
|
return "RtNetlinkAddressMessage{ "
|
||||||
|
|||||||
@@ -16,8 +16,11 @@
|
|||||||
|
|
||||||
package com.android.net.module.util.netlink;
|
package com.android.net.module.util.netlink;
|
||||||
|
|
||||||
|
import static android.system.OsConstants.IFA_F_PERMANENT;
|
||||||
import static android.system.OsConstants.NETLINK_ROUTE;
|
import static android.system.OsConstants.NETLINK_ROUTE;
|
||||||
|
import static android.system.OsConstants.RT_SCOPE_LINK;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
@@ -31,6 +34,8 @@ import androidx.test.runner.AndroidJUnit4;
|
|||||||
|
|
||||||
import com.android.net.module.util.HexDump;
|
import com.android.net.module.util.HexDump;
|
||||||
|
|
||||||
|
import libcore.util.HexEncoding;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
@@ -42,7 +47,7 @@ import java.nio.ByteOrder;
|
|||||||
@SmallTest
|
@SmallTest
|
||||||
public class RtNetlinkAddressMessageTest {
|
public class RtNetlinkAddressMessageTest {
|
||||||
private static final Inet6Address TEST_LINK_LOCAL =
|
private static final Inet6Address TEST_LINK_LOCAL =
|
||||||
(Inet6Address) InetAddresses.parseNumericAddress("fe80::2C41:5CFF:FE09:6665");
|
(Inet6Address) InetAddresses.parseNumericAddress("FE80::2C41:5CFF:FE09:6665");
|
||||||
|
|
||||||
// An example of the full RTM_NEWADDR message.
|
// An example of the full RTM_NEWADDR message.
|
||||||
private static final String RTM_NEWADDR_HEX =
|
private static final String RTM_NEWADDR_HEX =
|
||||||
@@ -127,6 +132,47 @@ public class RtNetlinkAddressMessageTest {
|
|||||||
assertNull(msg);
|
assertNull(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateRtmNewAddressMessage() {
|
||||||
|
// Hexadecimal representation of our created packet.
|
||||||
|
final String expectedNewAddressHex =
|
||||||
|
// struct nlmsghdr
|
||||||
|
"48000000" + // length = 72
|
||||||
|
"1400" + // type = 20 (RTM_NEWADDR)
|
||||||
|
"0501" + // flags = NLM_F_ACK | NLM_F_REQUEST | NLM_F_REPLACE
|
||||||
|
"01000000" + // seqno = 1
|
||||||
|
"00000000" + // pid = 0 (send to kernel)
|
||||||
|
// struct IfaddrMsg
|
||||||
|
"0A" + // family = inet6
|
||||||
|
"40" + // prefix len = 64
|
||||||
|
"80" + // flags = IFA_F_PERMANENT
|
||||||
|
"FD" + // scope = RT_SCOPE_LINK
|
||||||
|
"17000000" + // ifindex = 23
|
||||||
|
// struct nlattr: IFA_ADDRESS
|
||||||
|
"1400" + // len
|
||||||
|
"0100" + // type
|
||||||
|
"FE800000000000002C415CFFFE096665" + // IP address = fe80::2C41:5cff:fe09:6665
|
||||||
|
// struct nlattr: IFA_CACHEINFO
|
||||||
|
"1400" + // len
|
||||||
|
"0600" + // type
|
||||||
|
"FFFFFFFF" + // preferred = infinite
|
||||||
|
"FFFFFFFF" + // valid = infinite
|
||||||
|
"00000000" + // cstamp
|
||||||
|
"00000000" + // tstamp
|
||||||
|
// struct nlattr: IFA_FLAGS
|
||||||
|
"0800" + // len
|
||||||
|
"0800" + // type
|
||||||
|
"80000000"; // flags = IFA_F_PERMANENT
|
||||||
|
final byte[] expectedNewAddress =
|
||||||
|
HexEncoding.decode(expectedNewAddressHex.toCharArray(), false);
|
||||||
|
|
||||||
|
final byte[] bytes = RtNetlinkAddressMessage.newRtmNewAddressMessage(1 /* seqno */,
|
||||||
|
TEST_LINK_LOCAL, (short) 64 /* prefix len */, (byte) IFA_F_PERMANENT /* flags */,
|
||||||
|
(byte) RT_SCOPE_LINK /* scope */, 23 /* ifindex */,
|
||||||
|
(long) 0xFFFFFFFF /* preferred */, (long) 0xFFFFFFFF /* valid */);
|
||||||
|
assertArrayEquals(expectedNewAddress, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testToString() {
|
public void testToString() {
|
||||||
final ByteBuffer byteBuffer = toByteBuffer(RTM_NEWADDR_HEX);
|
final ByteBuffer byteBuffer = toByteBuffer(RTM_NEWADDR_HEX);
|
||||||
|
|||||||
Reference in New Issue
Block a user