blob: 92ec0c4e4c6403b2ba623b79af0204fd4bed8c79 [file] [log] [blame]
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.net.module.util.netlink;
import android.net.MacAddress;
import android.system.OsConstants;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import java.nio.ByteBuffer;
/**
* A NetlinkMessage subclass for rtnetlink link messages.
*
* RtNetlinkLinkMessage.parse() must be called with a ByteBuffer that contains exactly one netlink
* message.
*
* see also:
*
* include/uapi/linux/rtnetlink.h
*
* @hide
*/
public class RtNetlinkLinkMessage extends NetlinkMessage {
public static final short IFLA_ADDRESS = 1;
public static final short IFLA_IFNAME = 3;
public static final short IFLA_MTU = 4;
private int mMtu;
@NonNull
private StructIfinfoMsg mIfinfomsg;
@Nullable
private MacAddress mHardwareAddress;
@Nullable
private String mInterfaceName;
private RtNetlinkLinkMessage(@NonNull StructNlMsgHdr header) {
super(header);
mIfinfomsg = null;
mMtu = 0;
mHardwareAddress = null;
mInterfaceName = null;
}
public int getMtu() {
return mMtu;
}
@NonNull
public StructIfinfoMsg getIfinfoHeader() {
return mIfinfomsg;
}
@Nullable
public MacAddress getHardwareAddress() {
return mHardwareAddress;
}
@Nullable
public String getInterfaceName() {
return mInterfaceName;
}
/**
* Parse rtnetlink link message from {@link ByteBuffer}. This method must be called with a
* ByteBuffer that contains exactly one netlink message.
*
* @param header netlink message header.
* @param byteBuffer the ByteBuffer instance that wraps the raw netlink message bytes.
*/
@Nullable
public static RtNetlinkLinkMessage parse(@NonNull final StructNlMsgHdr header,
@NonNull final ByteBuffer byteBuffer) {
final RtNetlinkLinkMessage linkMsg = new RtNetlinkLinkMessage(header);
linkMsg.mIfinfomsg = StructIfinfoMsg.parse(byteBuffer);
if (linkMsg.mIfinfomsg == null) return null;
// IFLA_MTU
final int baseOffset = byteBuffer.position();
StructNlAttr nlAttr = StructNlAttr.findNextAttrOfType(IFLA_MTU, byteBuffer);
if (nlAttr != null) {
linkMsg.mMtu = nlAttr.getValueAsInt(0 /* default value */);
}
// IFLA_ADDRESS
byteBuffer.position(baseOffset);
nlAttr = StructNlAttr.findNextAttrOfType(IFLA_ADDRESS, byteBuffer);
if (nlAttr != null) {
linkMsg.mHardwareAddress = nlAttr.getValueAsMacAddress();
}
// IFLA_IFNAME
byteBuffer.position(baseOffset);
nlAttr = StructNlAttr.findNextAttrOfType(IFLA_IFNAME, byteBuffer);
if (nlAttr != null) {
linkMsg.mInterfaceName = nlAttr.getValueAsString();
}
return linkMsg;
}
/**
* Write a rtnetlink link message to {@link ByteBuffer}.
*/
@VisibleForTesting
protected void pack(ByteBuffer byteBuffer) {
getHeader().pack(byteBuffer);
mIfinfomsg.pack(byteBuffer);
if (mMtu != 0) {
final StructNlAttr mtu = new StructNlAttr(IFLA_MTU, mMtu);
mtu.pack(byteBuffer);
}
if (mHardwareAddress != null) {
final StructNlAttr hardwareAddress = new StructNlAttr(IFLA_ADDRESS, mHardwareAddress);
hardwareAddress.pack(byteBuffer);
}
if (mInterfaceName != null) {
final StructNlAttr ifname = new StructNlAttr(IFLA_IFNAME, mInterfaceName);
ifname.pack(byteBuffer);
}
}
@Override
public String toString() {
return "RtNetlinkLinkMessage{ "
+ "nlmsghdr{" + mHeader.toString(OsConstants.NETLINK_ROUTE) + "}, "
+ "Ifinfomsg{" + mIfinfomsg.toString() + "}, "
+ "Hardware Address{" + mHardwareAddress + "}, "
+ "MTU{" + mMtu + "}, "
+ "Ifname{" + mInterfaceName + "} "
+ "}";
}
}