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 java.nio.ByteBuffer; 20 21 22 /** 23 * struct nlmsghdr 24 * 25 * see <linux_src>/include/uapi/linux/netlink.h 26 * 27 * @hide 28 */ 29 public class StructNlMsgHdr { 30 // Already aligned. 31 public static final int STRUCT_SIZE = 16; 32 33 public static final short NLM_F_REQUEST = 0x0001; 34 public static final short NLM_F_MULTI = 0x0002; 35 public static final short NLM_F_ACK = 0x0004; 36 public static final short NLM_F_ECHO = 0x0008; 37 // Flags for a GET request. 38 public static final short NLM_F_ROOT = 0x0100; 39 public static final short NLM_F_MATCH = 0x0200; 40 public static final short NLM_F_DUMP = NLM_F_ROOT|NLM_F_MATCH; 41 // Flags for a NEW request. 42 public static final short NLM_F_REPLACE = 0x100; 43 public static final short NLM_F_EXCL = 0x200; 44 public static final short NLM_F_CREATE = 0x400; 45 public static final short NLM_F_APPEND = 0x800; 46 47 stringForNlMsgFlags(short flags)48 public static String stringForNlMsgFlags(short flags) { 49 final StringBuilder sb = new StringBuilder(); 50 if ((flags & NLM_F_REQUEST) != 0) { 51 sb.append("NLM_F_REQUEST"); 52 } 53 if ((flags & NLM_F_MULTI) != 0) { 54 if (sb.length() > 0) { sb.append("|"); } 55 sb.append("NLM_F_MULTI"); 56 } 57 if ((flags & NLM_F_ACK) != 0) { 58 if (sb.length() > 0) { sb.append("|"); } 59 sb.append("NLM_F_ACK"); 60 } 61 if ((flags & NLM_F_ECHO) != 0) { 62 if (sb.length() > 0) { sb.append("|"); } 63 sb.append("NLM_F_ECHO"); 64 } 65 if ((flags & NLM_F_ROOT) != 0) { 66 if (sb.length() > 0) { sb.append("|"); } 67 sb.append("NLM_F_ROOT"); 68 } 69 if ((flags & NLM_F_MATCH) != 0) { 70 if (sb.length() > 0) { sb.append("|"); } 71 sb.append("NLM_F_MATCH"); 72 } 73 return sb.toString(); 74 } 75 hasAvailableSpace(ByteBuffer byteBuffer)76 public static boolean hasAvailableSpace(ByteBuffer byteBuffer) { 77 return byteBuffer != null && byteBuffer.remaining() >= STRUCT_SIZE; 78 } 79 parse(ByteBuffer byteBuffer)80 public static StructNlMsgHdr parse(ByteBuffer byteBuffer) { 81 if (!hasAvailableSpace(byteBuffer)) { return null; } 82 83 // The ByteOrder must have already been set by the caller. In most 84 // cases ByteOrder.nativeOrder() is correct, with the exception 85 // of usage within unittests. 86 final StructNlMsgHdr struct = new StructNlMsgHdr(); 87 struct.nlmsg_len = byteBuffer.getInt(); 88 struct.nlmsg_type = byteBuffer.getShort(); 89 struct.nlmsg_flags = byteBuffer.getShort(); 90 struct.nlmsg_seq = byteBuffer.getInt(); 91 struct.nlmsg_pid = byteBuffer.getInt(); 92 93 if (struct.nlmsg_len < STRUCT_SIZE) { 94 // Malformed. 95 return null; 96 } 97 return struct; 98 } 99 100 public int nlmsg_len; 101 public short nlmsg_type; 102 public short nlmsg_flags; 103 public int nlmsg_seq; 104 public int nlmsg_pid; 105 StructNlMsgHdr()106 public StructNlMsgHdr() { 107 nlmsg_len = 0; 108 nlmsg_type = 0; 109 nlmsg_flags = 0; 110 nlmsg_seq = 0; 111 nlmsg_pid = 0; 112 } 113 pack(ByteBuffer byteBuffer)114 public void pack(ByteBuffer byteBuffer) { 115 // The ByteOrder must have already been set by the caller. In most 116 // cases ByteOrder.nativeOrder() is correct, with the possible 117 // exception of usage within unittests. 118 byteBuffer.putInt(nlmsg_len); 119 byteBuffer.putShort(nlmsg_type); 120 byteBuffer.putShort(nlmsg_flags); 121 byteBuffer.putInt(nlmsg_seq); 122 byteBuffer.putInt(nlmsg_pid); 123 } 124 125 @Override toString()126 public String toString() { 127 final String typeStr = "" + nlmsg_type 128 + "(" + NetlinkConstants.stringForNlMsgType(nlmsg_type) + ")"; 129 final String flagsStr = "" + nlmsg_flags 130 + "(" + stringForNlMsgFlags(nlmsg_flags) + ")"; 131 return "StructNlMsgHdr{ " 132 + "nlmsg_len{" + nlmsg_len + "}, " 133 + "nlmsg_type{" + typeStr + "}, " 134 + "nlmsg_flags{" + flagsStr + ")}, " 135 + "nlmsg_seq{" + nlmsg_seq + "}, " 136 + "nlmsg_pid{" + nlmsg_pid + "} " 137 + "}"; 138 } 139 } 140