1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.net.module.util.netlink; 18 19 import android.net.MacAddress; 20 import android.system.OsConstants; 21 22 import androidx.annotation.NonNull; 23 import androidx.annotation.Nullable; 24 import androidx.annotation.VisibleForTesting; 25 26 import java.nio.ByteBuffer; 27 28 /** 29 * A NetlinkMessage subclass for rtnetlink link messages. 30 * 31 * RtNetlinkLinkMessage.parse() must be called with a ByteBuffer that contains exactly one netlink 32 * message. 33 * 34 * see also: 35 * 36 * include/uapi/linux/rtnetlink.h 37 * 38 * @hide 39 */ 40 public class RtNetlinkLinkMessage extends NetlinkMessage { 41 public static final short IFLA_ADDRESS = 1; 42 public static final short IFLA_IFNAME = 3; 43 public static final short IFLA_MTU = 4; 44 public static final short IFLA_INET6_ADDR_GEN_MODE = 8; 45 public static final short IFLA_AF_SPEC = 26; 46 47 public static final short IN6_ADDR_GEN_MODE_NONE = 1; 48 49 private int mMtu; 50 @NonNull 51 private StructIfinfoMsg mIfinfomsg; 52 @Nullable 53 private MacAddress mHardwareAddress; 54 @Nullable 55 private String mInterfaceName; 56 RtNetlinkLinkMessage(@onNull StructNlMsgHdr header)57 private RtNetlinkLinkMessage(@NonNull StructNlMsgHdr header) { 58 super(header); 59 mIfinfomsg = null; 60 mMtu = 0; 61 mHardwareAddress = null; 62 mInterfaceName = null; 63 } 64 getMtu()65 public int getMtu() { 66 return mMtu; 67 } 68 69 @NonNull getIfinfoHeader()70 public StructIfinfoMsg getIfinfoHeader() { 71 return mIfinfomsg; 72 } 73 74 @Nullable getHardwareAddress()75 public MacAddress getHardwareAddress() { 76 return mHardwareAddress; 77 } 78 79 @Nullable getInterfaceName()80 public String getInterfaceName() { 81 return mInterfaceName; 82 } 83 84 /** 85 * Parse rtnetlink link message from {@link ByteBuffer}. This method must be called with a 86 * ByteBuffer that contains exactly one netlink message. 87 * 88 * @param header netlink message header. 89 * @param byteBuffer the ByteBuffer instance that wraps the raw netlink message bytes. 90 */ 91 @Nullable parse(@onNull final StructNlMsgHdr header, @NonNull final ByteBuffer byteBuffer)92 public static RtNetlinkLinkMessage parse(@NonNull final StructNlMsgHdr header, 93 @NonNull final ByteBuffer byteBuffer) { 94 final RtNetlinkLinkMessage linkMsg = new RtNetlinkLinkMessage(header); 95 96 linkMsg.mIfinfomsg = StructIfinfoMsg.parse(byteBuffer); 97 if (linkMsg.mIfinfomsg == null) return null; 98 99 // IFLA_MTU 100 final int baseOffset = byteBuffer.position(); 101 StructNlAttr nlAttr = StructNlAttr.findNextAttrOfType(IFLA_MTU, byteBuffer); 102 if (nlAttr != null) { 103 linkMsg.mMtu = nlAttr.getValueAsInt(0 /* default value */); 104 } 105 106 // IFLA_ADDRESS 107 byteBuffer.position(baseOffset); 108 nlAttr = StructNlAttr.findNextAttrOfType(IFLA_ADDRESS, byteBuffer); 109 if (nlAttr != null) { 110 linkMsg.mHardwareAddress = nlAttr.getValueAsMacAddress(); 111 } 112 113 // IFLA_IFNAME 114 byteBuffer.position(baseOffset); 115 nlAttr = StructNlAttr.findNextAttrOfType(IFLA_IFNAME, byteBuffer); 116 if (nlAttr != null) { 117 linkMsg.mInterfaceName = nlAttr.getValueAsString(); 118 } 119 120 return linkMsg; 121 } 122 123 /** 124 * Write a rtnetlink link message to {@link ByteBuffer}. 125 */ 126 @VisibleForTesting pack(ByteBuffer byteBuffer)127 protected void pack(ByteBuffer byteBuffer) { 128 getHeader().pack(byteBuffer); 129 mIfinfomsg.pack(byteBuffer); 130 131 if (mMtu != 0) { 132 final StructNlAttr mtu = new StructNlAttr(IFLA_MTU, mMtu); 133 mtu.pack(byteBuffer); 134 } 135 if (mHardwareAddress != null) { 136 final StructNlAttr hardwareAddress = new StructNlAttr(IFLA_ADDRESS, mHardwareAddress); 137 hardwareAddress.pack(byteBuffer); 138 } 139 if (mInterfaceName != null) { 140 final StructNlAttr ifname = new StructNlAttr(IFLA_IFNAME, mInterfaceName); 141 ifname.pack(byteBuffer); 142 } 143 } 144 145 @Override toString()146 public String toString() { 147 return "RtNetlinkLinkMessage{ " 148 + "nlmsghdr{" + mHeader.toString(OsConstants.NETLINK_ROUTE) + "}, " 149 + "Ifinfomsg{" + mIfinfomsg.toString() + "}, " 150 + "Hardware Address{" + mHardwareAddress + "}, " 151 + "MTU{" + mMtu + "}, " 152 + "Ifname{" + mInterfaceName + "} " 153 + "}"; 154 } 155 } 156