blob: ab9d2e6516b58485540fa0f71afdd03a0136f0d4 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.net.netlink;
import java.nio.ByteBuffer;
/**
* Base class for IPv6 neighbour discovery options.
*/
public class NdOption {
public static final int STRUCT_SIZE = 2;
/** The option type. */
public final byte type;
/** The length of the option in 8-byte units. Actually an unsigned 8-bit integer */
public final int length;
/** Constructs a new NdOption. */
NdOption(byte type, int length) {
this.type = type;
this.length = length;
}
/**
* Parses a neighbour discovery option.
*
* Parses (and consumes) the option if it is of a known type. If the option is of an unknown
* type, advances the buffer (so the caller can continue parsing if desired) and returns
* {@link #UNKNOWN}. If the option claims a length of 0, returns null because parsing cannot
* continue.
*
* No checks are performed on the length other than ensuring it is not 0, so if a caller wants
* to deal with options that might overflow the structure that contains them, it must explicitly
* set the buffer's limit to the position at which that structure ends.
*
* @param buf the buffer to parse.
* @return a subclass of {@link NdOption}, or {@code null} for an unknown or malformed option.
*/
public static NdOption parse(ByteBuffer buf) {
if (buf == null || buf.remaining() < STRUCT_SIZE) return null;
// Peek the type without advancing the buffer.
byte type = buf.get(buf.position());
int length = Byte.toUnsignedInt(buf.get(buf.position() + 1));
if (length == 0) return null;
switch (type) {
case StructNdOptPref64.TYPE:
return StructNdOptPref64.parse(buf);
default:
int newPosition = Math.min(buf.limit(), buf.position() + length * 8);
buf.position(newPosition);
return UNKNOWN;
}
}
void writeToByteBuffer(ByteBuffer buf) {
buf.put(type);
buf.put((byte) length);
}
@Override
public String toString() {
return String.format("NdOption(%d, %d)", Byte.toUnsignedInt(type), length);
}
public static final NdOption UNKNOWN = new NdOption((byte) 0, 0);
}