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