From d4de245c84debc1693c4c57f4d63a9de6b61c0fa Mon Sep 17 00:00:00 2001 From: Xiao Ma Date: Wed, 10 Sep 2025 22:51:13 +0900 Subject: [PATCH] Parse IFLA_INET6_FLAGS attr from the RTM_NEWLINK message. Flag: EXEMPT mainline change Bug: 293393743 Test: atest NetworkStaticLibTests Change-Id: I5dc34461a13bd0751d3d7debf1e7412f05958734 --- .../util/netlink/RtNetlinkLinkMessage.java | 75 +++++++++++++++++-- .../netlink/RtNetlinkLinkMessageTest.java | 29 ++++++- 2 files changed, 98 insertions(+), 6 deletions(-) diff --git a/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkLinkMessage.java b/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkLinkMessage.java index 4600e697c2..4e0d5e102c 100644 --- a/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkLinkMessage.java +++ b/staticlibs/device/com/android/net/module/util/netlink/RtNetlinkLinkMessage.java @@ -16,6 +16,7 @@ package com.android.net.module.util.netlink; +import static android.system.OsConstants.AF_INET6; import static android.system.OsConstants.AF_UNSPEC; import static com.android.net.module.util.NetworkStackConstants.ETHER_ADDR_LEN; @@ -53,6 +54,7 @@ public class RtNetlinkLinkMessage extends NetlinkMessage { public static final short IFLA_MTU = 4; public static final short IFLA_INET6_ADDR_GEN_MODE = 8; public static final short IFLA_AF_SPEC = 26; + public static final short IFLA_INET6_FLAGS = 1; public static final short IN6_ADDR_GEN_MODE_NONE = 1; @@ -60,6 +62,8 @@ public class RtNetlinkLinkMessage extends NetlinkMessage { private static final int IFNAMSIZ = 16; // The default value of MTU, which means the MTU is unspecified. private static final int DEFAULT_MTU = 0; + // The default value of IPv6 link attribute flags. + private static final int DEFAULT_IFLA_INET6_FLAGS = 0; @NonNull private final StructIfinfoMsg mIfinfomsg; @@ -69,6 +73,24 @@ public class RtNetlinkLinkMessage extends NetlinkMessage { @Nullable private final String mInterfaceName; + // IPv6 operational flags for the interface, from the IFLA_INET6_FLAGS netlink attribute. + // also see inet6_dev.if_flags in if_inet6.h + private final int mInet6Flags; + + /** + * Creates an {@link RtNetlinkLinkMessage} instance. + * + * @return A new {@link RtNetlinkLinkMessage} instance, or {@code null} if the input arguments + * are invalid. + */ + @Nullable + public static RtNetlinkLinkMessage build(@NonNull StructNlMsgHdr nlmsghdr, + @NonNull StructIfinfoMsg ifinfomsg, int mtu, @Nullable MacAddress hardwareAddress, + @Nullable String interfaceName) { + return RtNetlinkLinkMessage.build(nlmsghdr, ifinfomsg, mtu, hardwareAddress, interfaceName, + DEFAULT_IFLA_INET6_FLAGS); + } + /** * Creates an {@link RtNetlinkLinkMessage} instance. * @@ -80,13 +102,14 @@ public class RtNetlinkLinkMessage extends NetlinkMessage { * @param mtu The Maximum Transmission Unit (MTU) value for the link. * @param hardwareAddress The hardware address (MAC address) of the link. May be {@code null}. * @param interfaceName The name of the interface. May be {@code null}. + * @param inet6Flags IPv6 operational flags for the interface. * @return A new {@link RtNetlinkLinkMessage} instance, or {@code null} if the input arguments * are invalid. */ @Nullable public static RtNetlinkLinkMessage build(@NonNull StructNlMsgHdr nlmsghdr, @NonNull StructIfinfoMsg ifinfomsg, int mtu, @Nullable MacAddress hardwareAddress, - @Nullable String interfaceName) { + @Nullable String interfaceName, int inet6Flags) { if (mtu < 0) { return null; } @@ -96,17 +119,19 @@ public class RtNetlinkLinkMessage extends NetlinkMessage { } nlmsghdr.nlmsg_len = calculateMessageLength(mtu, hardwareAddress, interfaceName); - return new RtNetlinkLinkMessage(nlmsghdr, ifinfomsg, mtu, hardwareAddress, interfaceName); + return new RtNetlinkLinkMessage(nlmsghdr, ifinfomsg, mtu, hardwareAddress, interfaceName, + inet6Flags); } private RtNetlinkLinkMessage(@NonNull StructNlMsgHdr nlmsghdr, @NonNull StructIfinfoMsg ifinfomsg, int mtu, @Nullable MacAddress hardwareAddress, - @Nullable String interfaceName) { + @Nullable String interfaceName, int inet6Flags) { super(nlmsghdr); mIfinfomsg = ifinfomsg; mMtu = mtu; mHardwareAddress = hardwareAddress; mInterfaceName = interfaceName; + mInet6Flags = inet6Flags; } public int getMtu() { @@ -128,6 +153,10 @@ public class RtNetlinkLinkMessage extends NetlinkMessage { return mInterfaceName; } + public int getInet6Flags() { + return mInet6Flags; + } + /** * Parse rtnetlink link message from {@link ByteBuffer}. This method must be called with a * ByteBuffer that contains exactly one netlink message. @@ -171,7 +200,42 @@ public class RtNetlinkLinkMessage extends NetlinkMessage { return null; } - return new RtNetlinkLinkMessage(header, ifinfoMsg, mtu, hardwareAddress, interfaceName); + /* + * IFLA_AF_SPEC: + * Contains nested attributes for address family specific attributes. + * Each address family may create a attribute with the address family + * number as type and create its own attribute structure in it. + * + * Example: + * [IFLA_AF_SPEC] = { + * [AF_INET] = { + * [IFLA_INET_CONF] = ..., + * }, + * [AF_INET6] = { + * [IFLA_INET6_FLAGS] = ..., + * [IFLA_INET6_CONF] = ..., + * } + * } + */ + int inet6Flags = DEFAULT_IFLA_INET6_FLAGS; + byteBuffer.position(baseOffset); + nlAttr = StructNlAttr.findNextAttrOfType(IFLA_AF_SPEC, byteBuffer); + if (nlAttr != null) { + final StructNlAttr ipv6ConfigAttrs = StructNlAttr.findNextAttrOfType( + (short) AF_INET6, + nlAttr.getValueAsByteBuffer()); + if (ipv6ConfigAttrs != null) { + final StructNlAttr inet6FlagsAttr = StructNlAttr.findNextAttrOfType( + IFLA_INET6_FLAGS, + ipv6ConfigAttrs.getValueAsByteBuffer()); + if (inet6FlagsAttr != null) { + inet6Flags = inet6FlagsAttr.getValueAsInt(DEFAULT_IFLA_INET6_FLAGS); + } + } + } + + return new RtNetlinkLinkMessage(header, ifinfoMsg, mtu, hardwareAddress, interfaceName, + inet6Flags); } /** @@ -368,7 +432,8 @@ public class RtNetlinkLinkMessage extends NetlinkMessage { + "Ifinfomsg{" + mIfinfomsg + "}, " + "Hardware Address{" + mHardwareAddress + "}, " + "MTU{" + mMtu + "}, " - + "Ifname{" + mInterfaceName + "} " + + "Ifname{" + mInterfaceName + "}, " + + "IFLA_INET6_FLAGS{" + mInet6Flags + "} " + "}"; } } diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkLinkMessageTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkLinkMessageTest.java index 9c60354ae1..ffdcb962dd 100644 --- a/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkLinkMessageTest.java +++ b/staticlibs/tests/unit/src/com/android/net/module/util/netlink/RtNetlinkLinkMessageTest.java @@ -332,7 +332,8 @@ public class RtNetlinkLinkMessageTest { + "Ifinfomsg{" + "family: 0, type: 1, index: 30, flags: 4098, change: 0}, " + "Hardware Address{92:c3:e3:c9:37:4e}, " + "MTU{1500}, " - + "Ifname{wlan0} " + + "Ifname{wlan0}, " + + "IFLA_INET6_FLAGS{0} " + "}"; assertEquals(expected, linkMsg.toString()); } @@ -358,4 +359,30 @@ public class RtNetlinkLinkMessageTest { final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer, NETLINK_ROUTE); assertNull(msg); } + + @Test + public void testParseRtNetlinkMessageWithMOrOBit() { + final String msgBytes = + "7C000000100000000100000000000000" // nlmsghdr (16 bytes) + + "000001000200000043100000FFFFFFFF" // ifinfomsg (16 bytes) + + "090003006574683000000000" // IFLA_IFNAME (12 bytes) + + "50001A00" // IFLA_AF_SPEC (84 bytes) + + "1C000200" // Nested AF_INET (28 bytes) + + "18000100" // Nested IFLA_INET_CONF (24 bytes) + + "0000000000000000000000000000000000000000" // 20 bytes of dummy payload + + "30000A00" // Nested AF_INET6 (48 bytes) + + "08000100C0000000" // Nested IFLA_INET6_FLAGS (8 bytes): M=1,O=1 + + "24000600" // Nested IFLA_INET6_CONF (36 bytes) + + "00000000000000000000000000000000" // 16 bytes of dummy payload + + "00000000000000000000000000000000"; // 16 bytes of dummy payload + + final ByteBuffer byteBuffer = toByteBuffer(msgBytes); + byteBuffer.order(ByteOrder.LITTLE_ENDIAN); // For testing. + final NetlinkMessage msg = NetlinkMessage.parse(byteBuffer, NETLINK_ROUTE); + assertNotNull(msg); + assertTrue(msg instanceof RtNetlinkLinkMessage); + final RtNetlinkLinkMessage linkMsg = (RtNetlinkLinkMessage) msg; + final int flags = linkMsg.getInet6Flags(); + assertEquals(0xC0, flags); + } }