1 /* 2 * Copyright (C) 2020 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 * Base class for IPv6 neighbour discovery options. 23 */ 24 public class NdOption { 25 public static final int STRUCT_SIZE = 2; 26 27 /** The option type. */ 28 public final byte type; 29 /** The length of the option in 8-byte units. Actually an unsigned 8-bit integer */ 30 public final int length; 31 32 /** Constructs a new NdOption. */ 33 NdOption(byte type, int length) { 34 this.type = type; 35 this.length = length; 36 } 37 38 /** 39 * Parses a neighbour discovery option. 40 * 41 * Parses (and consumes) the option if it is of a known type. If the option is of an unknown 42 * type, advances the buffer (so the caller can continue parsing if desired) and returns 43 * {@link #UNKNOWN}. If the option claims a length of 0, returns null because parsing cannot 44 * continue. 45 * 46 * No checks are performed on the length other than ensuring it is not 0, so if a caller wants 47 * to deal with options that might overflow the structure that contains them, it must explicitly 48 * set the buffer's limit to the position at which that structure ends. 49 * 50 * @param buf the buffer to parse. 51 * @return a subclass of {@link NdOption}, or {@code null} for an unknown or malformed option. 52 */ 53 public static NdOption parse(ByteBuffer buf) { 54 if (buf == null || buf.remaining() < STRUCT_SIZE) return null; 55 56 // Peek the type without advancing the buffer. 57 byte type = buf.get(buf.position()); 58 int length = Byte.toUnsignedInt(buf.get(buf.position() + 1)); 59 if (length == 0) return null; 60 61 switch (type) { 62 case StructNdOptPref64.TYPE: 63 return StructNdOptPref64.parse(buf); 64 65 default: 66 int newPosition = Math.min(buf.limit(), buf.position() + length * 8); 67 buf.position(newPosition); 68 return UNKNOWN; 69 } 70 } 71 72 void writeToByteBuffer(ByteBuffer buf) { 73 buf.put(type); 74 buf.put((byte) length); 75 } 76 77 @Override 78 public String toString() { 79 return String.format("NdOption(%d, %d)", Byte.toUnsignedInt(type), length); 80 } 81 82 public static final NdOption UNKNOWN = new NdOption((byte) 0, 0); 83 } 84