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 17 package android.net.netlink; 18 19 import android.net.netlink.NetlinkConstants; 20 import libcore.io.SizeOf; 21 22 import java.net.InetAddress; 23 import java.net.UnknownHostException; 24 import java.nio.ByteOrder; 25 import java.nio.ByteBuffer; 26 27 28 /** 29 * struct nlattr 30 * 31 * see: <linux_src>/include/uapi/linux/netlink.h 32 * 33 * @hide 34 */ 35 public class StructNlAttr { 36 // Already aligned. 37 public static final int NLA_HEADERLEN = 4; 38 39 // Return a (length, type) object only, without consuming any bytes in 40 // |byteBuffer| and without copying or interpreting any value bytes. 41 // This is used for scanning over a packed set of struct nlattr's, 42 // looking for instances of a particular type. peek(ByteBuffer byteBuffer)43 public static StructNlAttr peek(ByteBuffer byteBuffer) { 44 if (byteBuffer == null || byteBuffer.remaining() < NLA_HEADERLEN) { 45 return null; 46 } 47 final int baseOffset = byteBuffer.position(); 48 49 final StructNlAttr struct = new StructNlAttr(); 50 struct.nla_len = byteBuffer.getShort(); 51 struct.nla_type = byteBuffer.getShort(); 52 struct.mByteOrder = byteBuffer.order(); 53 54 byteBuffer.position(baseOffset); 55 if (struct.nla_len < NLA_HEADERLEN) { 56 // Malformed. 57 return null; 58 } 59 return struct; 60 } 61 parse(ByteBuffer byteBuffer)62 public static StructNlAttr parse(ByteBuffer byteBuffer) { 63 final StructNlAttr struct = peek(byteBuffer); 64 if (struct == null || byteBuffer.remaining() < struct.getAlignedLength()) { 65 return null; 66 } 67 68 final int baseOffset = byteBuffer.position(); 69 byteBuffer.position(baseOffset + NLA_HEADERLEN); 70 71 int valueLen = ((int) struct.nla_len) & 0xffff; 72 valueLen -= NLA_HEADERLEN; 73 if (valueLen > 0) { 74 struct.nla_value = new byte[valueLen]; 75 byteBuffer.get(struct.nla_value, 0, valueLen); 76 byteBuffer.position(baseOffset + struct.getAlignedLength()); 77 } 78 return struct; 79 } 80 81 public short nla_len; 82 public short nla_type; 83 public byte[] nla_value; 84 public ByteOrder mByteOrder; 85 StructNlAttr()86 public StructNlAttr() { 87 mByteOrder = ByteOrder.nativeOrder(); 88 } 89 getAlignedLength()90 public int getAlignedLength() { 91 return NetlinkConstants.alignedLengthOf(nla_len); 92 } 93 getValueAsByteBuffer()94 public ByteBuffer getValueAsByteBuffer() { 95 if (nla_value == null) { return null; } 96 final ByteBuffer byteBuffer = ByteBuffer.wrap(nla_value); 97 byteBuffer.order(mByteOrder); 98 return byteBuffer; 99 } 100 getValueAsInt(int defaultValue)101 public int getValueAsInt(int defaultValue) { 102 final ByteBuffer byteBuffer = getValueAsByteBuffer(); 103 if (byteBuffer == null || byteBuffer.remaining() != SizeOf.INT) { 104 return defaultValue; 105 } 106 return getValueAsByteBuffer().getInt(); 107 } 108 getValueAsInetAddress()109 public InetAddress getValueAsInetAddress() { 110 if (nla_value == null) { return null; } 111 112 try { 113 return InetAddress.getByAddress(nla_value); 114 } catch (UnknownHostException ignored) { 115 return null; 116 } 117 } 118 pack(ByteBuffer byteBuffer)119 public void pack(ByteBuffer byteBuffer) { 120 final int originalPosition = byteBuffer.position(); 121 byteBuffer.putShort(nla_len); 122 byteBuffer.putShort(nla_type); 123 byteBuffer.put(nla_value); 124 byteBuffer.position(originalPosition + getAlignedLength()); 125 } 126 127 @Override toString()128 public String toString() { 129 return "StructNlAttr{ " 130 + "nla_len{" + nla_len + "}, " 131 + "nla_type{" + nla_type + "}, " 132 + "nla_value{" + NetlinkConstants.hexify(nla_value) + "}, " 133 + "}"; 134 } 135 } 136