RtNetlinkNeighborMessage.java revision 9ce5d602cd5d732ae10efe0b648b43ddf60d65c9
16193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline/* 26193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * Copyright (C) 2015 The Android Open Source Project 36193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * 46193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * Licensed under the Apache License, Version 2.0 (the "License"); 56193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * you may not use this file except in compliance with the License. 66193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * You may obtain a copy of the License at 76193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * 86193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * http://www.apache.org/licenses/LICENSE-2.0 96193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * 106193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * Unless required by applicable law or agreed to in writing, software 116193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * distributed under the License is distributed on an "AS IS" BASIS, 126193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * See the License for the specific language governing permissions and 146193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * limitations under the License. 156193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline */ 166193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 176193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klinepackage android.net.netlink; 186193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 196193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport android.net.netlink.StructNdaCacheInfo; 206193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport android.net.netlink.StructNdMsg; 216193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport android.net.netlink.StructNlAttr; 226193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport android.net.netlink.StructNlMsgHdr; 236193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport android.net.netlink.NetlinkMessage; 249ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Klineimport android.system.OsConstants; 256193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport android.util.Log; 266193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 276193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport java.net.InetAddress; 289ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Klineimport java.net.Inet6Address; 296193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport java.nio.ByteBuffer; 306193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport java.nio.ByteOrder; 316193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 326193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 336193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline/** 346193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * A NetlinkMessage subclass for netlink error messages. 356193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * 366193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * see also: <linux_src>/include/uapi/linux/neighbour.h 376193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * 386193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * @hide 396193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline */ 406193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klinepublic class RtNetlinkNeighborMessage extends NetlinkMessage { 416193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline public static final short NDA_UNSPEC = 0; 426193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline public static final short NDA_DST = 1; 436193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline public static final short NDA_LLADDR = 2; 446193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline public static final short NDA_CACHEINFO = 3; 456193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline public static final short NDA_PROBES = 4; 466193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline public static final short NDA_VLAN = 5; 476193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline public static final short NDA_PORT = 6; 486193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline public static final short NDA_VNI = 7; 496193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline public static final short NDA_IFINDEX = 8; 506193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline public static final short NDA_MASTER = 9; 516193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 526193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline private static StructNlAttr findNextAttrOfType(short attrType, ByteBuffer byteBuffer) { 536193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline while (byteBuffer != null && byteBuffer.remaining() > 0) { 546193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline final StructNlAttr nlAttr = StructNlAttr.peek(byteBuffer); 556193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline if (nlAttr == null) { 566193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline break; 576193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 586193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline if (nlAttr.nla_type == attrType) { 596193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline return StructNlAttr.parse(byteBuffer); 606193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 616193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline if (byteBuffer.remaining() < nlAttr.getAlignedLength()) { 626193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline break; 636193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 646193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline byteBuffer.position(byteBuffer.position() + nlAttr.getAlignedLength()); 656193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 666193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline return null; 676193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 686193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 696193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline public static RtNetlinkNeighborMessage parse(StructNlMsgHdr header, ByteBuffer byteBuffer) { 706193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline final RtNetlinkNeighborMessage neighMsg = new RtNetlinkNeighborMessage(header); 716193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 726193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline neighMsg.mNdmsg = StructNdMsg.parse(byteBuffer); 736193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline if (neighMsg.mNdmsg == null) { 746193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline return null; 756193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 766193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 776193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline // Some of these are message-type dependent, and not always present. 786193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline final int baseOffset = byteBuffer.position(); 796193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline StructNlAttr nlAttr = findNextAttrOfType(NDA_DST, byteBuffer); 806193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline if (nlAttr != null) { 816193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline neighMsg.mDestination = nlAttr.getValueAsInetAddress(); 826193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 836193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 846193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline byteBuffer.position(baseOffset); 856193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline nlAttr = findNextAttrOfType(NDA_LLADDR, byteBuffer); 866193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline if (nlAttr != null) { 876193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline neighMsg.mLinkLayerAddr = nlAttr.nla_value; 886193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 896193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 906193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline byteBuffer.position(baseOffset); 916193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline nlAttr = findNextAttrOfType(NDA_PROBES, byteBuffer); 926193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline if (nlAttr != null) { 936193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline neighMsg.mNumProbes = nlAttr.getValueAsInt(0); 946193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 956193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 966193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline byteBuffer.position(baseOffset); 976193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline nlAttr = findNextAttrOfType(NDA_CACHEINFO, byteBuffer); 986193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline if (nlAttr != null) { 996193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline neighMsg.mCacheInfo = StructNdaCacheInfo.parse(nlAttr.getValueAsByteBuffer()); 1006193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 1016193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 1026193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline final int kMinConsumed = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE; 1036193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline final int kAdditionalSpace = NetlinkConstants.alignedLengthOf( 1046193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline neighMsg.mHeader.nlmsg_len - kMinConsumed); 1056193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline if (byteBuffer.remaining() < kAdditionalSpace) { 1066193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline byteBuffer.position(byteBuffer.limit()); 1076193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } else { 1086193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline byteBuffer.position(baseOffset + kAdditionalSpace); 1096193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 1106193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 1116193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline return neighMsg; 1126193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 1136193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 1146193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline /** 1156193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * A convenience method to create an RTM_GETNEIGH request message. 1166193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline */ 1176193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline public static byte[] newGetNeighborsRequest(int seqNo) { 1186193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline final int length = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE; 1196193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline final byte[] bytes = new byte[length]; 1206193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); 1216193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline byteBuffer.order(ByteOrder.nativeOrder()); 1226193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 1236193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr(); 1246193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline nlmsghdr.nlmsg_len = length; 1256193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline nlmsghdr.nlmsg_type = NetlinkConstants.RTM_GETNEIGH; 1266193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline nlmsghdr.nlmsg_flags = StructNlMsgHdr.NLM_F_REQUEST|StructNlMsgHdr.NLM_F_DUMP; 1276193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline nlmsghdr.nlmsg_seq = seqNo; 1286193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline nlmsghdr.pack(byteBuffer); 1296193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 1306193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline final StructNdMsg ndmsg = new StructNdMsg(); 1316193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline ndmsg.pack(byteBuffer); 1326193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 1336193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline return bytes; 1346193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 1356193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 1369ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline /** 1379ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline * A convenience method to create an RTM_NEWNEIGH message, to modify 1389ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline * the kernel's state information for a specific neighbor. 1399ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline */ 1409ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline public static byte[] newNewNeighborMessage( 1419ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline int seqNo, InetAddress ip, short nudState, int ifIndex, byte[] llAddr) { 1429ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline final StructNlMsgHdr nlmsghdr = new StructNlMsgHdr(); 1439ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline nlmsghdr.nlmsg_type = NetlinkConstants.RTM_NEWNEIGH; 1449ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline nlmsghdr.nlmsg_flags = StructNlMsgHdr.NLM_F_REQUEST | StructNlMsgHdr.NLM_F_REPLACE; 1459ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline nlmsghdr.nlmsg_seq = seqNo; 1469ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline 1479ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline final RtNetlinkNeighborMessage msg = new RtNetlinkNeighborMessage(nlmsghdr); 1489ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline msg.mNdmsg = new StructNdMsg(); 1499ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline msg.mNdmsg.ndm_family = 1509ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline (byte) ((ip instanceof Inet6Address) ? OsConstants.AF_INET6 : OsConstants.AF_INET); 1519ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline msg.mNdmsg.ndm_ifindex = ifIndex; 1529ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline msg.mNdmsg.ndm_state = nudState; 1539ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline msg.mDestination = ip; 1549ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline msg.mLinkLayerAddr = llAddr; // might be null 1559ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline 1569ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline final byte[] bytes = new byte[msg.getRequiredSpace()]; 1579ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline nlmsghdr.nlmsg_len = bytes.length; 1589ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline final ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); 1599ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline byteBuffer.order(ByteOrder.nativeOrder()); 1609ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline msg.pack(byteBuffer); 1619ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline return bytes; 1629ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline } 1639ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline 1646193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline private StructNdMsg mNdmsg; 1656193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline private InetAddress mDestination; 1666193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline private byte[] mLinkLayerAddr; 1676193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline private int mNumProbes; 1686193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline private StructNdaCacheInfo mCacheInfo; 1696193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 1706193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline private RtNetlinkNeighborMessage(StructNlMsgHdr header) { 1716193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline super(header); 1726193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline mNdmsg = null; 1736193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline mDestination = null; 1746193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline mLinkLayerAddr = null; 1756193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline mNumProbes = 0; 1766193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline mCacheInfo = null; 1776193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 1786193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 1796193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline public StructNdMsg getNdHeader() { 1806193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline return mNdmsg; 1816193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 1826193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 1836193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline public InetAddress getDestination() { 1846193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline return mDestination; 1856193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 1866193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 1876193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline public byte[] getLinkLayerAddress() { 1886193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline return mLinkLayerAddr; 1896193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 1906193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 1916193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline public int getProbes() { 1926193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline return mNumProbes; 1936193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 1946193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 1956193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline public StructNdaCacheInfo getCacheInfo() { 1966193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline return mCacheInfo; 1976193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 1986193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline 1999ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline public int getRequiredSpace() { 2009ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline int spaceRequired = StructNlMsgHdr.STRUCT_SIZE + StructNdMsg.STRUCT_SIZE; 2019ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline if (mDestination != null) { 2029ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline spaceRequired += NetlinkConstants.alignedLengthOf( 2039ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline StructNlAttr.NLA_HEADERLEN + mDestination.getAddress().length); 2049ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline } 2059ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline if (mLinkLayerAddr != null) { 2069ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline spaceRequired += NetlinkConstants.alignedLengthOf( 2079ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline StructNlAttr.NLA_HEADERLEN + mLinkLayerAddr.length); 2089ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline } 2099ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline // Currently we don't write messages with NDA_PROBES nor NDA_CACHEINFO 2109ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline // attributes appended. Fix later, if necessary. 2119ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline return spaceRequired; 2129ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline } 2139ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline 2149ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline private static void packNlAttr(short nlType, byte[] nlValue, ByteBuffer byteBuffer) { 2159ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline final StructNlAttr nlAttr = new StructNlAttr(); 2169ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline nlAttr.nla_type = nlType; 2179ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline nlAttr.nla_value = nlValue; 2189ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline nlAttr.nla_len = (short) (StructNlAttr.NLA_HEADERLEN + nlAttr.nla_value.length); 2199ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline nlAttr.pack(byteBuffer); 2209ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline } 2219ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline 2229ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline public void pack(ByteBuffer byteBuffer) { 2239ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline getHeader().pack(byteBuffer) ; 2249ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline mNdmsg.pack(byteBuffer); 2259ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline 2269ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline if (mDestination != null) { 2279ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline packNlAttr(NDA_DST, mDestination.getAddress(), byteBuffer); 2289ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline } 2299ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline if (mLinkLayerAddr != null) { 2309ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline packNlAttr(NDA_LLADDR, mLinkLayerAddr, byteBuffer); 2319ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline } 2329ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline } 2339ce5d602cd5d732ae10efe0b648b43ddf60d65c9Erik Kline 2346193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline @Override 2356193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline public String toString() { 2366193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline final String ipLiteral = (mDestination == null) ? "" : mDestination.getHostAddress(); 2376193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline return "RtNetlinkNeighborMessage{ " 2386193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline + "nlmsghdr{" + (mHeader == null ? "" : mHeader.toString()) + "}, " 2396193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline + "ndmsg{" + (mNdmsg == null ? "" : mNdmsg.toString()) + "}, " 2406193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline + "destination{" + ipLiteral + "} " 2416193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline + "linklayeraddr{" + NetlinkConstants.hexify(mLinkLayerAddr) + "} " 2426193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline + "probes{" + mNumProbes + "} " 2436193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline + "cacheinfo{" + (mCacheInfo == null ? "" : mCacheInfo.toString()) + "} " 2446193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline + "}"; 2456193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline } 2466193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline} 247