1 /* 2 * Copyright (C) 2019 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 android.net.netlink; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.system.OsConstants; 22 23 import java.nio.ByteBuffer; 24 25 26 /** 27 * NetlinkMessage base class for other, more specific netlink message types. 28 * 29 * Classes that extend NetlinkMessage should: 30 * - implement a public static parse(StructNlMsgHdr, ByteBuffer) method 31 * - returning either null (parse errors) or a new object of the subclass 32 * type (cast-able to NetlinkMessage) 33 * 34 * NetlinkMessage.parse() should be updated to know which nlmsg_type values 35 * correspond with which message subclasses. 36 * 37 * @hide 38 */ 39 public class NetlinkMessage { 40 private final static String TAG = "NetlinkMessage"; 41 42 /** 43 * Parsing netlink messages for reserved control message or specific netlink message. The 44 * netlink family is required for parsing specific netlink message. See man-pages/netlink. 45 */ 46 @Nullable parse(@onNull ByteBuffer byteBuffer, int nlFamily)47 public static NetlinkMessage parse(@NonNull ByteBuffer byteBuffer, int nlFamily) { 48 final int startPosition = (byteBuffer != null) ? byteBuffer.position() : -1; 49 final StructNlMsgHdr nlmsghdr = StructNlMsgHdr.parse(byteBuffer); 50 if (nlmsghdr == null) { 51 return null; 52 } 53 54 int payloadLength = NetlinkConstants.alignedLengthOf(nlmsghdr.nlmsg_len); 55 payloadLength -= StructNlMsgHdr.STRUCT_SIZE; 56 if (payloadLength < 0 || payloadLength > byteBuffer.remaining()) { 57 // Malformed message or runt buffer. Pretend the buffer was consumed. 58 byteBuffer.position(byteBuffer.limit()); 59 return null; 60 } 61 62 // Reserved control messages. The netlink family is ignored. 63 // See NLMSG_MIN_TYPE in include/uapi/linux/netlink.h. 64 if (nlmsghdr.nlmsg_type <= NetlinkConstants.NLMSG_MAX_RESERVED) { 65 return parseCtlMessage(nlmsghdr, byteBuffer, payloadLength); 66 } 67 68 // Netlink family messages. The netlink family is required. Note that the reason for using 69 // if-statement is that switch-case can't be used because the OsConstants.NETLINK_* are 70 // not constant. 71 if (nlFamily == OsConstants.NETLINK_ROUTE) { 72 return parseRtMessage(nlmsghdr, byteBuffer); 73 } else if (nlFamily == OsConstants.NETLINK_INET_DIAG) { 74 return parseInetDiagMessage(nlmsghdr, byteBuffer); 75 } else if (nlFamily == OsConstants.NETLINK_NETFILTER) { 76 return parseNfMessage(nlmsghdr, byteBuffer); 77 } 78 79 return null; 80 } 81 82 protected StructNlMsgHdr mHeader; 83 NetlinkMessage(StructNlMsgHdr nlmsghdr)84 public NetlinkMessage(StructNlMsgHdr nlmsghdr) { 85 mHeader = nlmsghdr; 86 } 87 getHeader()88 public StructNlMsgHdr getHeader() { 89 return mHeader; 90 } 91 92 @Override toString()93 public String toString() { 94 // The netlink family is not provided to StructNlMsgHdr#toString because NetlinkMessage 95 // doesn't store the information. So the netlink message type can't be transformed into 96 // a string by StructNlMsgHdr#toString and just keep as an integer. The specific message 97 // which inherits NetlinkMessage could override NetlinkMessage#toString and provide the 98 // specific netlink family to StructNlMsgHdr#toString. 99 return "NetlinkMessage{" + (mHeader == null ? "" : mHeader.toString()) + "}"; 100 } 101 102 @NonNull parseCtlMessage(@onNull StructNlMsgHdr nlmsghdr, @NonNull ByteBuffer byteBuffer, int payloadLength)103 private static NetlinkMessage parseCtlMessage(@NonNull StructNlMsgHdr nlmsghdr, 104 @NonNull ByteBuffer byteBuffer, int payloadLength) { 105 switch (nlmsghdr.nlmsg_type) { 106 case NetlinkConstants.NLMSG_ERROR: 107 return (NetlinkMessage) NetlinkErrorMessage.parse(nlmsghdr, byteBuffer); 108 default: { 109 // Other netlink control messages. Just parse the header for now, 110 // pretending the whole message was consumed. 111 byteBuffer.position(byteBuffer.position() + payloadLength); 112 return new NetlinkMessage(nlmsghdr); 113 } 114 } 115 } 116 117 @Nullable parseRtMessage(@onNull StructNlMsgHdr nlmsghdr, @NonNull ByteBuffer byteBuffer)118 private static NetlinkMessage parseRtMessage(@NonNull StructNlMsgHdr nlmsghdr, 119 @NonNull ByteBuffer byteBuffer) { 120 switch (nlmsghdr.nlmsg_type) { 121 case NetlinkConstants.RTM_NEWNEIGH: 122 case NetlinkConstants.RTM_DELNEIGH: 123 case NetlinkConstants.RTM_GETNEIGH: 124 return (NetlinkMessage) RtNetlinkNeighborMessage.parse(nlmsghdr, byteBuffer); 125 case NetlinkConstants.RTM_NEWNDUSEROPT: 126 return (NetlinkMessage) NduseroptMessage.parse(nlmsghdr, byteBuffer); 127 default: return null; 128 } 129 } 130 131 @Nullable parseInetDiagMessage(@onNull StructNlMsgHdr nlmsghdr, @NonNull ByteBuffer byteBuffer)132 private static NetlinkMessage parseInetDiagMessage(@NonNull StructNlMsgHdr nlmsghdr, 133 @NonNull ByteBuffer byteBuffer) { 134 switch (nlmsghdr.nlmsg_type) { 135 case NetlinkConstants.SOCK_DIAG_BY_FAMILY: 136 return (NetlinkMessage) InetDiagMessage.parse(nlmsghdr, byteBuffer); 137 default: return null; 138 } 139 } 140 141 @Nullable parseNfMessage(@onNull StructNlMsgHdr nlmsghdr, @NonNull ByteBuffer byteBuffer)142 private static NetlinkMessage parseNfMessage(@NonNull StructNlMsgHdr nlmsghdr, 143 @NonNull ByteBuffer byteBuffer) { 144 switch (nlmsghdr.nlmsg_type) { 145 case NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8 146 | NetlinkConstants.IPCTNL_MSG_CT_NEW: 147 case NetlinkConstants.NFNL_SUBSYS_CTNETLINK << 8 148 | NetlinkConstants.IPCTNL_MSG_CT_DELETE: 149 return (NetlinkMessage) ConntrackMessage.parse(nlmsghdr, byteBuffer); 150 default: return null; 151 } 152 } 153 } 154