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.NetlinkConstants;
206193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport android.net.netlink.NetlinkErrorMessage;
216193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport android.net.netlink.RtNetlinkNeighborMessage;
226193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport android.net.netlink.StructNlAttr;
236193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport android.net.netlink.StructNlMsgHdr;
246193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport android.util.Log;
256193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
266193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klineimport java.nio.ByteBuffer;
276193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
286193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
296193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline/**
306193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * NetlinkMessage base class for other, more specific netlink message types.
316193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline *
326193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * Classes that extend NetlinkMessage should:
336193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline *     - implement a public static parse(StructNlMsgHdr, ByteBuffer) method
346193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline *     - returning either null (parse errors) or a new object of the subclass
356193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline *       type (cast-able to NetlinkMessage)
366193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline *
376193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * NetlinkMessage.parse() should be updated to know which nlmsg_type values
386193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * correspond with which message subclasses.
396193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline *
406193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline * @hide
416193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline */
426193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Klinepublic class NetlinkMessage {
436193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline    private final static String TAG = "NetlinkMessage";
446193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
456193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline    public static NetlinkMessage parse(ByteBuffer byteBuffer) {
466193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        final int startPosition = (byteBuffer != null) ? byteBuffer.position() : -1;
476193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        final StructNlMsgHdr nlmsghdr = StructNlMsgHdr.parse(byteBuffer);
486193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        if (nlmsghdr == null) {
496193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline            return null;
506193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        }
516193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
526193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        int payloadLength = NetlinkConstants.alignedLengthOf(nlmsghdr.nlmsg_len);
536193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        payloadLength -= StructNlMsgHdr.STRUCT_SIZE;
546193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        if (payloadLength < 0 || payloadLength > byteBuffer.remaining()) {
556193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline            // Malformed message or runt buffer.  Pretend the buffer was consumed.
566193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline            byteBuffer.position(byteBuffer.limit());
576193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline            return null;
586193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        }
596193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
606193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        switch (nlmsghdr.nlmsg_type) {
616193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline            //case NetlinkConstants.NLMSG_NOOP:
626193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline            case NetlinkConstants.NLMSG_ERROR:
63cef7bc939fbc3baae5ccf78dcef63fc60e07ae21Erik Kline                return (NetlinkMessage) NetlinkErrorMessage.parse(nlmsghdr, byteBuffer);
646193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline            case NetlinkConstants.NLMSG_DONE:
656193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                byteBuffer.position(byteBuffer.position() + payloadLength);
666193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                return new NetlinkMessage(nlmsghdr);
676193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline            //case NetlinkConstants.NLMSG_OVERRUN:
686193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline            case NetlinkConstants.RTM_NEWNEIGH:
696193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline            case NetlinkConstants.RTM_DELNEIGH:
706193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline            case NetlinkConstants.RTM_GETNEIGH:
716193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                return (NetlinkMessage) RtNetlinkNeighborMessage.parse(nlmsghdr, byteBuffer);
726193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline            default:
736193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                if (nlmsghdr.nlmsg_type <= NetlinkConstants.NLMSG_MAX_RESERVED) {
746193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                    // Netlink control message.  Just parse the header for now,
756193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                    // pretending the whole message was consumed.
766193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                    byteBuffer.position(byteBuffer.position() + payloadLength);
776193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                    return new NetlinkMessage(nlmsghdr);
786193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                }
796193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline                return null;
806193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        }
816193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline    }
826193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
836193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline    protected StructNlMsgHdr mHeader;
846193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
856193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline    public NetlinkMessage(StructNlMsgHdr nlmsghdr) {
866193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        mHeader = nlmsghdr;
876193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline    }
886193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
896193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline    public StructNlMsgHdr getHeader() {
906193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        return mHeader;
916193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline    }
926193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline
936193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline    @Override
946193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline    public String toString() {
956193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline        return "NetlinkMessage{" + (mHeader == null ? "" : mHeader.toString()) + "}";
966193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline    }
976193aa3305bc2aa5b7f0a983f4b08c99065cfb82Erik Kline}
98