1/* 2 * Copyright (C) 2015 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 17package android.net.netlink; 18 19import android.net.netlink.NetlinkConstants; 20import android.net.netlink.NetlinkErrorMessage; 21import android.net.netlink.RtNetlinkNeighborMessage; 22import android.net.netlink.StructNlAttr; 23import android.net.netlink.StructNlMsgHdr; 24import android.util.Log; 25 26import java.nio.ByteBuffer; 27 28 29/** 30 * NetlinkMessage base class for other, more specific netlink message types. 31 * 32 * Classes that extend NetlinkMessage should: 33 * - implement a public static parse(StructNlMsgHdr, ByteBuffer) method 34 * - returning either null (parse errors) or a new object of the subclass 35 * type (cast-able to NetlinkMessage) 36 * 37 * NetlinkMessage.parse() should be updated to know which nlmsg_type values 38 * correspond with which message subclasses. 39 * 40 * @hide 41 */ 42public class NetlinkMessage { 43 private final static String TAG = "NetlinkMessage"; 44 45 public static NetlinkMessage parse(ByteBuffer byteBuffer) { 46 final int startPosition = (byteBuffer != null) ? byteBuffer.position() : -1; 47 final StructNlMsgHdr nlmsghdr = StructNlMsgHdr.parse(byteBuffer); 48 if (nlmsghdr == null) { 49 return null; 50 } 51 52 int payloadLength = NetlinkConstants.alignedLengthOf(nlmsghdr.nlmsg_len); 53 payloadLength -= StructNlMsgHdr.STRUCT_SIZE; 54 if (payloadLength < 0 || payloadLength > byteBuffer.remaining()) { 55 // Malformed message or runt buffer. Pretend the buffer was consumed. 56 byteBuffer.position(byteBuffer.limit()); 57 return null; 58 } 59 60 switch (nlmsghdr.nlmsg_type) { 61 //case NetlinkConstants.NLMSG_NOOP: 62 case NetlinkConstants.NLMSG_ERROR: 63 return (NetlinkMessage) NetlinkErrorMessage.parse(nlmsghdr, byteBuffer); 64 case NetlinkConstants.NLMSG_DONE: 65 byteBuffer.position(byteBuffer.position() + payloadLength); 66 return new NetlinkMessage(nlmsghdr); 67 //case NetlinkConstants.NLMSG_OVERRUN: 68 case NetlinkConstants.RTM_NEWNEIGH: 69 case NetlinkConstants.RTM_DELNEIGH: 70 case NetlinkConstants.RTM_GETNEIGH: 71 return (NetlinkMessage) RtNetlinkNeighborMessage.parse(nlmsghdr, byteBuffer); 72 default: 73 if (nlmsghdr.nlmsg_type <= NetlinkConstants.NLMSG_MAX_RESERVED) { 74 // Netlink control message. Just parse the header for now, 75 // pretending the whole message was consumed. 76 byteBuffer.position(byteBuffer.position() + payloadLength); 77 return new NetlinkMessage(nlmsghdr); 78 } 79 return null; 80 } 81 } 82 83 protected StructNlMsgHdr mHeader; 84 85 public NetlinkMessage(StructNlMsgHdr nlmsghdr) { 86 mHeader = nlmsghdr; 87 } 88 89 public StructNlMsgHdr getHeader() { 90 return mHeader; 91 } 92 93 @Override 94 public String toString() { 95 return "NetlinkMessage{" + (mHeader == null ? "" : mHeader.toString()) + "}"; 96 } 97} 98