Files
KLALB/src/org/kne/cloud/network/ipv6/IPv6Packet.java
T

1403 lines
45 KiB
Java

package org.kne.cloud.network.ipv6;
import java.io.EOFException;
import java.io.IOException;
import java.io.StreamCorruptedException;
import java.net.Inet6Address;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.klalb.KLALBPacket;
import org.kne.cloud.network.kltp.KLTPPacket;
import org.kne.cloud.network.srv6.IPv6SegmentRoutingTLV;
import org.kne.cloud.network.tcp.UDPPacket;
import org.kne.io.KNEChannels;
/**
* IPv6数据包类,继承自NetworkPacket,用于处理IPv6网络数据包
*/
public class IPv6Packet extends NetworkPacket {
private static final boolean debug=false;
// ==================== IPv6扩展头类型 ====================
/** 逐跳选项头 - RFC 8200 */
public static final int HOP_BY_HOP_OPTIONS = 0;
/** ICMPv4 - RFC 792 */
public static final int ICMPv4 = 1;
/** IGMP - RFC 1112 */
public static final int IGMP = 2;
/** IPv4封装 - RFC 2003 */
public static final int IPv4 = 4;
/** TCP - RFC 793 */
public static final int TCP = 6;
/** EGP - RFC 888 */
public static final int EGP = 8;
/** IGP - RFC 891 */
public static final int IGP = 9;
/** UDP - RFC 768 */
public static final int UDP = 17;
/** IPv6封装 - RFC 2473 */
public static final int IPv6 = 41;
/** 路由头 - RFC 8200 */
public static final int ROUTING = 43;
/** 分片头 - RFC 8200 */
public static final int FRAGMENT = 44;
/** RSVP - RFC 2205 */
public static final int RSVP = 46;
/** GRE - RFC 2784 */
public static final int GRE = 47;
/** 封装安全载荷 - RFC 4303 */
public static final int ESP = 50;
/** 认证头 - RFC 4302 */
public static final int AH = 51;
/** ICMPv6 - RFC 4443 */
public static final int ICMPv6 = 58;
/** 无下一个头 - RFC 8200 */
public static final int NO_NEXT_HEADER = 59;
/** 目的选项头 - RFC 8200 */
public static final int DESTINATION_OPTIONS = 60;
/** 移动IPv6 - RFC 6275 */
public static final int MOBILITY = 135;
/** Shim6 - RFC 5533 */
public static final int SHIM6 = 140;
/** 实验性和测试用途 - RFC 3692 */
public static final int EXPERIMENTAL_1 = 253;
/** 实验性和测试用途 - RFC 3692 */
public static final int EXPERIMENTAL_2 = 254;
/** 保留 - RFC 8200 */
public static final int RESERVED = 255;
// ==================== 上层协议类型 ====================
/** OSPF - RFC 2328 */
public static final int OSPF = 89;
/** SCTP - RFC 4960 */
public static final int SCTP = 132;
/** MPLS in IP - RFC 4023 */
public static final int MPLS_IN_IP = 137;
/** MANET协议 - RFC 5498 */
public static final int MANET = 138;
// ==================== 特殊用途 ====================
/** IPv6选项 - RFC 8200 */
public static final int IPv6_OPTIONS = 0;
/** 主机身份协议HIP(HOST_IDENTITY_PROTOCOL) - RFC 5201 */
public static final int HIP = 139;
/** 无线接入网协议 - RFC 5845 */
public static final int WARP = 142;
// ==================== SRv6相关常量 ====================
/** SRv6路由类型 */
public static final int SRV6_ROUTING_TYPE = 4;
// ==================== 地址相关常量 ====================
/** IPv6地址长度(字节) */
public static final int IPV6_ADDRESS_LENGTH = 16;
/** IPv6地址长整型部分数量 */
public static final int IPV6_ADDRESS_LONGS = 2;
// ==================== 位操作相关常量 ====================
public static final int BIT_MASK_LOW_4_BITS = 0b00001111;
public static final int BIT_MASK_HIGH_4_BITS = 0b11110000;
public static final int BIT_MASK_LOW_8_BITS = 0xFF;
public static final int BIT_MASK_LOW_16_BITS = 0xFFFF;
public static final int BIT_MASK_LOW_32_BITS = 0xFFFFFFFF;
// ==================== 扩展头对齐常量 ====================
public static final int EXT_HEADER_ALIGNMENT = 8;
// ==================== 工具方法 ====================
/**
* 获取Next Header的名称
*/
public static String getName(int nextHeader) {
switch (nextHeader) {
case HOP_BY_HOP_OPTIONS: return "Hop-by-Hop Options";
case ICMPv4: return "ICMPv4";
case IGMP: return "IGMP";
case IPv4: return "IPv4";
case TCP: return "TCP";
case EGP: return "EGP";
case IGP: return "IGP";
case UDP: return "UDP";
case IPv6: return "IPv6";
case ROUTING: return "Routing Header";
case FRAGMENT: return "Fragment Header";
case RSVP: return "RSVP";
case GRE: return "GRE";
case ESP: return "Encapsulating Security Payload";
case AH: return "Authentication Header";
case ICMPv6: return "ICMPv6";
case NO_NEXT_HEADER: return "No Next Header";
case DESTINATION_OPTIONS: return "Destination Options";
case MOBILITY: return "Mobility Header";
case HIP: return "Host Identity Protocol";
case SHIM6: return "Shim6 Protocol";
case EXPERIMENTAL_1: return "Experimental #1";
case EXPERIMENTAL_2: return "Experimental #2";
case RESERVED: return "Reserved";
case OSPF: return "OSPF";
case SCTP: return "SCTP";
case MPLS_IN_IP: return "MPLS in IP";
case MANET: return "MANET Protocols";
case WARP: return "WARP";
default: return "Unknown (" + nextHeader + ")";
}
}
/**
* 检查是否为IPv6扩展头
*/
public static boolean isExtensionHeader(int nextHeader) {
return nextHeader == HOP_BY_HOP_OPTIONS ||
nextHeader == ROUTING ||
nextHeader == FRAGMENT ||
nextHeader == DESTINATION_OPTIONS ||
nextHeader == MOBILITY ||
nextHeader == HIP ||
nextHeader == SHIM6;
}
/**
* 检查是否为传输层协议
*/
public static boolean isTransportProtocol(int nextHeader) {
return nextHeader == TCP ||
nextHeader == UDP ||
nextHeader == SCTP;
}
/**
* 检查是否为网络层协议
*/
public static boolean isNetworkProtocol(int nextHeader) {
return nextHeader == IPv4 ||
nextHeader == IPv6 ||
nextHeader == ICMPv4 ||
nextHeader == ICMPv6;
}
// TTL是否已减少的标志
private boolean TTLdecreased = false;
public boolean isTTLdecreased() {
return TTLdecreased;
}
public void setTTLdecreased(boolean tTLdecreased) {
TTLdecreased = tTLdecreased;
}
// IPv6头部数据缓冲区
private ByteBuffer IPv6header;
private IPv6HopByHopHeader hopByHopHeader;
private IPv6RoutingHeader routingHeader;
// IPv6扩展头部列表
private List<IPv6ExtHeader> headers = new ArrayList<>();
// IPv6负载数据
private IPv6Payload payload;
// IPv6头部固定长度
public static final int IPv6_HEADER_LENGTH = 40;
// IPv6地址在头部中的偏移量
private static final int SOURCE_ADDRESS_OFFSET = 8;
private static final int DESTINATION_ADDRESS_OFFSET = 24;
public IPv6Payload getPayload() {
return payload;
}
public void setPayload(IPv6Payload payload) {
this.payload = payload;
}
/**
* 默认构造函数,初始化IPv6头部缓冲区
*/
public IPv6Packet() {
IPv6header = NetworkPacket.bufferAllocator.allocate(IPv6_HEADER_LENGTH);
}
/**
* 从字节中提取IP版本号
* @param b 字节数据
* @return IP版本号
*/
public static int getIPVersion(byte b) {
return b >>> 4;
}
/**
* 获取IPv6版本号
* @return 版本号
*/
public int getVersion() {
return IPv6header.get(0) >>> 4;
}
/**
* 设置IPv6版本号
* @param version 版本号
*/
public void setVersion(int version) {
IPv6header.put(0, (byte) (IPv6header.get(0) & BIT_MASK_LOW_4_BITS | version << 4));
}
/**
* 获取流量类别
* @return 流量类别
*/
public int getTrafficClass() {
// 读取字节 0 和字节 1 组成一个 short(16 位)
short firstTwoBytes = IPv6header.getShort(0);
// 提取 Traffic Class:高 4 位(Version)去掉,剩下就是 8 位 Traffic Class
return (firstTwoBytes & 0x0FF0) >>> 4;
}
/**
* 设置流量类别
* @param trafficClass 流量类别
*/
public void setTrafficClass(int trafficClass) {
// 读取当前的两个字节
short firstTwoBytes = IPv6header.getShort(0);
// 清除原来的 Traffic Class 位(将中间 8 位清零)
short cleared = (short) (firstTwoBytes & 0xF00F); // 保留高 4 位和低 4 位
// 组合新的 Traffic Class
short newValue = (short) (cleared | ((trafficClass & 0xFF) << 4));
// 一次性写回
IPv6header.putShort(0, newValue);
}
/**
* 检查是否启用ECN(显式拥塞通知)
* @return 是否启用ECN
*/
public boolean isEnableECN() {
return (IPv6header.get(1) & 0b00110000) != 0;
}
/**
* 启用ECN(显式拥塞通知)
*/
public void enableECN() {
IPv6header.put(1, (byte) ((IPv6header.get(1) & 0b11101111) | 0b00100000));
}
/**
* 标记CE(拥塞经历)
*/
public void markCE() {
byte g=IPv6header.get(1);
if((g& 0b00110000) != 0) {
// 启用ECN
IPv6header.put(1, (byte) ( g| 0b00110000));
}
// new Exception().printStackTrace();
}
/**
* 检查是否标记了CE(拥塞经历)
* @return 是否标记了CE
*/
public boolean isCE() {
return ((IPv6header.get(1) >>> 4) & 0b11) == 0b11;
}
/**
* 获取流标签
* @return 流标签
*/
public int getFlowLabel() {
// 读取前 4 个字节(32 位)
int firstWord = IPv6header.getInt(0);
// 提取 Flow Label:高 12 位(Version + Traffic Class)去掉,剩下低 20 位
return firstWord & 0x000FFFFF;
}
/**
* 设置流标签
* @param flowLabel 流标签
*/
public void setFlowLabel(int flowLabel) {
// 读取当前前 4 个字节
int firstWord = IPv6header.getInt(0);
// 清除原来的 Flow Label(将低 20 位清零)
int cleared = firstWord & 0xFFF00000; // 保留高 12 位
// 组合新的 Flow Label(只取低 20 位)
int newWord = cleared | (flowLabel & 0x000FFFFF);
// 一次性写回
IPv6header.putInt(0, newWord);
}
/**
* 获取负载长度
* @return 负载长度
*/
public int getPayloadLength() {
return IPv6header.getShort(4) & BIT_MASK_LOW_16_BITS;
}
/**
* 设置负载长度
* @param payloadLength 负载长度
*/
public void setPayloadLength(int payloadLength) {
IPv6header.putShort(4, (short) payloadLength);
}
/**
* 获取下一个头部协议类型
* @return 下一个头部协议类型
*/
public int getNextHeader() {
return IPv6header.get(6) & BIT_MASK_LOW_8_BITS;
}
/**
* 设置下一个头部协议类型
* @param nextHeader 下一个头部协议类型
*/
public void setNextHeader(int nextHeader) {
IPv6header.put(6, (byte) nextHeader);
}
/**
* 获取跳数限制
* @return 跳数限制
*/
public int getHopLimit() {
return IPv6header.get(7) & BIT_MASK_LOW_8_BITS;
}
/**
* 设置跳数限制
* @param hopLimit 跳数限制
*/
public void setHopLimit(int hopLimit) {
IPv6header.put(7, (byte) hopLimit);
}
/**
* 获取原始源地址字节数组
* @param sourceAddress 用于存储源地址的字节数组
*/
public void getRawSourceAddressArray(byte[] sourceAddress) {
IPv6header.get(SOURCE_ADDRESS_OFFSET, sourceAddress, 0, sourceAddress.length);
}
/**
* 设置原始源地址字节数组
* @param sourceAddress 源地址字节数组
*/
public void setRawSourceAddressArray(byte[] sourceAddress) {
IPv6header.put(SOURCE_ADDRESS_OFFSET, sourceAddress, 0, sourceAddress.length);
}
/**
* 获取原始目标地址字节数组
* @param destinationAddress 用于存储目标地址的字节数组
*/
public void getRawDestinationAddressArray(byte[] destinationAddress) {
IPv6header.get(DESTINATION_ADDRESS_OFFSET, destinationAddress, 0, destinationAddress.length);
}
/**
* 设置原始目标地址字节数组
* @param destinationAddress 目标地址字节数组
*/
public void setRawDestinationAddressArray(byte[] destinationAddress) {
IPv6header.put(DESTINATION_ADDRESS_OFFSET, destinationAddress, 0, destinationAddress.length);
}
/**
* 获取原始源地址字节数组
* @return
*/
public IPv6Address getSourceAddress() {
return IPv6Address.valueOf(SOURCE_ADDRESS_OFFSET,IPv6header);
}
/**
* 设置原始源地址字节数组
* @param sourceAddress 源地址字节数组
*/
public void setSourceAddress(IPv6Address sourceAddress) {
sourceAddress.writeTo(SOURCE_ADDRESS_OFFSET,IPv6header);
}
/**
* 获取原始目标地址字节数组
*/
public IPv6Address getDestinationAddress() {
return IPv6Address.valueOf(DESTINATION_ADDRESS_OFFSET,IPv6header);
}
/**
* 设置原始目标地址字节数组
* @param destinationAddress 目标地址字节数组
*/
public void setDestinationAddress(IPv6Address destinationAddress) {
destinationAddress.writeTo(DESTINATION_ADDRESS_OFFSET,IPv6header);
}
/**
* 获取源地址
* @return 源地址
*/
public Inet6Address getSourceAddress2() {
byte[] b = new byte[IPV6_ADDRESS_LENGTH];
IPv6header.get(SOURCE_ADDRESS_OFFSET, b, 0, b.length);
try {
return (Inet6Address) Inet6Address.getByAddress(b);
} catch (UnknownHostException e) {
return null;
}
}
/**
* 设置源地址
* @param sourceAddress 源地址
*/
public void setSourceAddress2(Inet6Address sourceAddress) {
byte[] b = sourceAddress.getAddress();
IPv6header.put(SOURCE_ADDRESS_OFFSET, b, 0, b.length);
}
/**
* 获取目标地址
* @return 目标地址
*/
public Inet6Address getDestinationAddress2() {
byte[] b = new byte[IPV6_ADDRESS_LENGTH];
IPv6header.get(DESTINATION_ADDRESS_OFFSET, b, 0, b.length);
try {
return (Inet6Address) Inet6Address.getByAddress(b);
} catch (UnknownHostException e) {
return null;
}
}
/**
* 设置目标地址
* @param destinationAddress 目标地址
*/
public void setDestinationAddress2(Inet6Address destinationAddress) {
byte[] b = destinationAddress.getAddress();
IPv6header.put(DESTINATION_ADDRESS_OFFSET, b, 0, b.length);
}
/**
* 获取流会话信息
* @return 流会话对象
*/
public FlowSession getFlowSession() {
return new FlowSession(getSourceAddress(), getDestinationAddress(), getFlowLabel());
}
/**
* 计算负载长度
* @return 负载长度
*/
private int calcPayloadLength() {
int lth = 0;
for (int i = 0; i < headers.size(); i++) {
int extHeaderLength=(int) headers.get(i).getTotalLength();
if(extHeaderLength<=0) {
throw new IllegalArgumentException("extHeaderLength:"+extHeaderLength+"<0");
}
lth += extHeaderLength;
}
lth += payload.getTotalLength();
return lth;
}
/**
* 获取数据包总长度
* @return 数据包总长度
*/
@Override
public long getTotalLength() {
return calcPayloadLength() + IPv6_HEADER_LENGTH;
}
/**
* 将数据包写入通道
* @param dto 可写字节通道
* @throws IOException 写入异常
*/
@Override
public void writeToChannel(WritableByteChannel dto) throws IOException {
if (headers.isEmpty()) {
setNextHeader(payload.getProtocolNumber());
} else {
setNextHeader(headers.get(0).getProtocolNumber());
}
setPayloadLength(calcPayloadLength());
dto.write(IPv6header.slice(0, IPv6header.limit()));
for (int i = 0; i < headers.size(); i++) {
IPv6ExtHeader exth = headers.get(i);
if (i + 1 < headers.size()) {
exth.setNextHeader(headers.get(i + 1).getProtocolNumber());
} else {
exth.setNextHeader(payload.getProtocolNumber());
}
exth.writeToChannel(dto);
}
payload.writeToChannel(dto);
if(debug)
debug("send");
}
/**
* 从通道读取数据包
* @param din 可读字节通道
* @param length 数据长度
* @throws IOException 读取异常
*/
@Override
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
IPv6header.limit(IPv6_HEADER_LENGTH);
IPv6header.position(0);
while (IPv6header.hasRemaining()) {
if (din.read(IPv6header) == -1) {
throw new EOFException();
}
}
int payloadlength = getPayloadLength();
int nextheader = getNextHeader();
loop: while (true) {
IPv6ExtHeader ext;
switch (nextheader) {
case HOP_BY_HOP_OPTIONS: // Hop-by-Hop选项头部
ext = new IPv6HopByHopHeader();
ext.readFromChannel(din, 0);
nextheader = ext.getNextHeader();
payloadlength -= ext.getTotalLength();
headers.add(ext);
hopByHopHeader=(IPv6HopByHopHeader) ext;
break;
case DESTINATION_OPTIONS: // 目标选项头部
ext = new IPv6DestinationHeader();
ext.readFromChannel(din, 0);
nextheader = ext.getNextHeader();
payloadlength -= ext.getTotalLength();
headers.add(ext);
break;
case ROUTING: // 路由头部
ByteBuffer bbf = NetworkPacket.bufferAllocator.allocate(2048);
bbf.limit(4);
while (bbf.hasRemaining()) {
if (din.read(bbf) == -1) {
throw new EOFException();
}
}
int routingType = bbf.get(2) & BIT_MASK_LOW_8_BITS;
switch (routingType) {
case SRV6_ROUTING_TYPE: // SRv6路由类型
ext = new IPv6SegmentRoutingHeader(bbf);
break;
default: // 其他路由类型
ext = new IPv6RoutingHeader(-1, bbf);
break;
}
ext.readFromChannel(din, 0);
nextheader = ext.getNextHeader();
payloadlength -= ext.getTotalLength();
headers.add(ext);
routingHeader=(IPv6RoutingHeader) ext;
break;
case FRAGMENT: // 分段头部
ext = new IPv6ExtHeader(nextheader);
ext.readFromChannel(din, 0);
nextheader = ext.getNextHeader();
payloadlength -= ext.getTotalLength();
headers.add(ext);
break;
case ESP: // ESP头部
ext = new IPv6ExtHeader(nextheader);
ext.readFromChannel(din, 0);
nextheader = ext.getNextHeader();
payloadlength -= ext.getTotalLength();
headers.add(ext);
break;
case AH: // AH头部
ext = new IPv6ExtHeader(nextheader);
ext.readFromChannel(din, 0);
nextheader = ext.getNextHeader();
payloadlength -= ext.getTotalLength();
headers.add(ext);
break;
case NO_NEXT_HEADER: // 无下一个头部
ext = new IPv6ExtHeader(nextheader);
ext.readFromChannel(din, 0);
nextheader = ext.getNextHeader();
payloadlength -= ext.getTotalLength();
headers.add(ext);
break;
case ICMPv6:
ICMPv6Packet icmp=ICMPv6Packet.readICMPv6PacketFromChannel(din,payloadlength);
icmp.setParent(this);
this.payload=icmp;
break loop;
case UDP: // UDP协议
UDPPacket udp=new UDPPacket();
udp.setParent(this);
udp.readFromChannel(din,payloadlength);
this.payload=udp;
break loop;
case KLALBPacket.KLALB_PROTOCOL_NUMBER: // KLALB协议
KLALBPacket kp = KLALBPacket.readKLALBPacketFromChannel(din);
this.payload = kp;
break loop;
case KLTPPacket.KLTP_PROTOCOL_NUMBER: //KLTP协议
IPv6Payload epld = KLTPPacket.readKLTPPacketFromChannel(din);
this.payload = epld;
break loop;
default: // 其他协议类型
IPv6Payload pld = new IPv6DefaultPayload(nextheader);
pld.readFromChannel(din, payloadlength);
this.payload = pld;
break loop;
}
}
if(debug)
debug("recv");
}
private void debug(String description) {
StringBuilder sb=new StringBuilder();
sb.append(description);
sb.append(" total:");
sb.append(getPayloadLength());
sb.append(" ");
for (IPv6ExtHeader iPv6ExtHeader : headers) {
sb.append(iPv6ExtHeader.getTotalLength());
sb.append(' ');
}
if(payload!=null)
sb.append(payload.getTotalLength());
System.out.println(sb);
}
/**
* 转换为字符串表示
* @return 字符串表示
*/
@Override
public String toString() {
return "IPv6Packet [getVersion()=" + getVersion() + ", getTrafficClass()=" + getTrafficClass()
+ ", getFlowLabel()=" + getFlowLabel() + ", getPayloadLength()=" + getPayloadLength()
+ ", getNextHeader()=" + getNextHeader() + ", getHopLimit()=" + getHopLimit() + ", getSourceAddress()="
+ getSourceAddress() + ", getDestinationAddress()=" + getDestinationAddress() + ", getLength()="
+ getTotalLength() + ", headers=" + headers + ", payload=" + payload + "]";
}
/**
* IPv6负载数据类
*/
public static abstract class IPv6Payload extends NetworkPacket {
private IPv6Packet parent;
private int protocolNumber;
public IPv6Payload(int protocolNumber) {
this.protocolNumber=protocolNumber;
}
public int getProtocolNumber() {
return protocolNumber;
}
@Override
protected boolean needEndPosition() {
return true;
}
public void setParent(IPv6Packet parent) {
this.parent = parent;
}
public IPv6Packet getParent() {
return parent;
}
}
public static class IPv6DefaultPayload extends IPv6Payload{
private ByteBuffer data;
public ByteBuffer getData() {
return data;
}
public IPv6DefaultPayload(int protocolNumber) {
super(protocolNumber);
this.data = NetworkPacket.bufferAllocator.allocate(65535);
}
public long getTotalLength() {
return data.limit();
}
@Override
public void writeToChannel(WritableByteChannel dto) throws IOException {
dto.write(data.slice(0, data.limit()));
}
@Override
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
data.limit((int) length);
while (data.hasRemaining()) {
if (din.read(data) == -1) {
throw new EOFException();
}
}
}
}
/**
* IPv6扩展头部基类
*/
public static class IPv6ExtHeader extends NetworkPacket {
private ByteBuffer data;
private int protocolNumber;
private int bufferLength;
@Override
public String toString() {
return "IPv6ExtHeader [protocolNumber=" + protocolNumber + ", getNextHeader()=" + getNextHeader()
+ ", getExtLength()=" + getExtLength() + "]";
}
public ByteBuffer getData() {
return data;
}
public IPv6ExtHeader(int type) {
this(type, -1);
}
protected IPv6ExtHeader(int protocolNumber, int bufferLength) {
this.protocolNumber = protocolNumber;
this.bufferLength=bufferLength;
if (bufferLength==-1) {
this.data = NetworkPacket.bufferAllocator.allocate(2048);
} else {
this.data = NetworkPacket.bufferAllocator.allocate(bufferLength);
}
}
protected IPv6ExtHeader(int protocolNumber, int bufferLength, ByteBuffer data) {
this.protocolNumber = protocolNumber;
this.bufferLength = bufferLength;
this.data = data;
}
public int getProtocolNumber() {
return protocolNumber;
}
public int getNextHeader() {
return data.get(0) & BIT_MASK_LOW_8_BITS;
}
public void setNextHeader(int nextHeader) {
data.put(0, (byte) nextHeader);
}
public int getExtLength() {
return data.get(1) & BIT_MASK_LOW_8_BITS;
}
protected void setExtLength(int extLength) {
data.put(1, (byte) extLength);
}
public long getTotalLength() {
return data.limit();
}
@Override
public void writeToChannel(WritableByteChannel dto) throws IOException {
if (bufferLength==-1) {
int ext = (data.limit() - EXT_HEADER_ALIGNMENT) / EXT_HEADER_ALIGNMENT;
setExtLength(ext);
dto.write(data.slice(0, data.limit()));
} else {
dto.write(data.slice(0, bufferLength));
}
}
@Override
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
data.limit(bufferLength);
while (data.hasRemaining()) {
if (din.read(data) == -1) {
throw new EOFException();
}
}
if (bufferLength==-1) {
int newLimit = getExtLength() * EXT_HEADER_ALIGNMENT + data.limit();
data.limit(newLimit);
while (data.hasRemaining()) {
if (din.read(data) == -1) {
throw new EOFException();
}
}
}
}
@Override
protected boolean needEndPosition() {
return false;
}
}
/**
* IPv6逐跳头部类
*/
public static class IPv6HopByHopHeader extends IPv6ExtHeader {
private final List<IPv6HopByHopTLV> tlvs = new ArrayList<IPv6HopByHopTLV>();
@Override
public String toString() {
return "IPv6HopByHopHeader [tlvs=" + tlvs + ", getProtocolNumber()=" + getProtocolNumber()
+ ", getNextHeader()=" + getNextHeader() + ", getExtLength()=" + getExtLength() + "]";
}
public IPv6HopByHopHeader() {
super(HOP_BY_HOP_OPTIONS,2);
}
public IPv6HopByHopHeader( ByteBuffer data) {
super(HOP_BY_HOP_OPTIONS, 2, data);
}
@Override
public void writeToChannel(WritableByteChannel dto) throws IOException {
int exl = calcTLVLength();
if ((exl+2) % EXT_HEADER_ALIGNMENT != 0) {
throw new StreamCorruptedException("extLength % " + EXT_HEADER_ALIGNMENT + " !=0");
}
setExtLength(((exl+2) / EXT_HEADER_ALIGNMENT)-1);
super.writeToChannel(dto);
for (IPv6HopByHopTLV tlv : tlvs) {
IPv6HopByHopTLV.writeIPv6HopByHopTLVToChannel(dto, tlv);
}
}
private int calcTLVLength() {
int tlvsl = 0;
for (IPv6HopByHopTLV tlve : tlvs) {
tlvsl += tlve.getTotalLength();
}
return tlvsl;
}
@Override
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
super.readFromChannel(din, length);
int extl = getExtLength();
// 计算应该读取的总字节数
int expectedTotalBytes = (extl + 1) * EXT_HEADER_ALIGNMENT;
int tlvBytesToRead = expectedTotalBytes - 2; // 减去基础头的2字节
tlvs.clear();
int bytesRead = 0;
// 读取直到达到预期的字节数
while (bytesRead < tlvBytesToRead) {
IPv6HopByHopTLV tlv = IPv6HopByHopTLV.readIPv6HopByHopTLVFromChannel(din);
int tlvLength = (int) tlv.getTotalLength();
// 检查是否会超出预期范围
if (bytesRead + tlvLength > tlvBytesToRead) {
throw new StreamCorruptedException(
String.format("TLV overflow: read %d + %d > %d bytes",
bytesRead, tlvLength, tlvBytesToRead));
}
tlvs.add(tlv);
bytesRead += tlvLength;
}
// 验证实际读取的字节数与预期一致
if (bytesRead != tlvBytesToRead) {
throw new StreamCorruptedException(
String.format("TLV length mismatch: expected %d, got %d",
tlvBytesToRead, bytesRead));
}
}
@Override
public long getTotalLength() {
return calcTLVLength() + 2;
}
public List<IPv6HopByHopTLV> getTlvs() {
return tlvs;
}
}
/**
* IPv6路由头部类
*/
public static class IPv6RoutingHeader extends IPv6ExtHeader {
@Override
public String toString() {
return "IPv6RoutingHeader [protocolNumber=" + getProtocolNumber() + ", getNextHeader()=" + getNextHeader()
+ ", getExtLength()=" + getExtLength() + ", getRoutingType()=" + getRoutingType() + "]";
}
public IPv6RoutingHeader() {
super(ROUTING);
}
public IPv6RoutingHeader(int bufferLength) {
super(ROUTING, bufferLength);
}
public IPv6RoutingHeader(int bufferLength, ByteBuffer data) {
super(ROUTING, bufferLength, data);
}
public int getRoutingType() {
return getData().get(2) & BIT_MASK_LOW_8_BITS;
}
public void setRoutingType(int routingTypr) {
getData().put(2, (byte) routingTypr);
}
public int getSegmentsLeft() {
return getData().get(3);
}
public void setSegmentsLeft(int segmentsLeft) {
getData().put(3, (byte) segmentsLeft);
}
}
/**
* IPv6段路由头部类
*/
/**
* IPv6 Segment Routing Header (SRH) 实现
*
* <p>根据 RFC 8754 实现,支持SRv6扩展头和TLV选项</p>
*
* <pre>
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Next Header | Hdr Ext Len | Routing Type | Segments Left |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Last Entry | Flags | Tag |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* | Segment List[0] (128-bit IPv6 address) |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ... |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* | Segment List[n] (128-bit IPv6 address) |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* // //
* // Optional Type-Length-Value objects (variable) //
* // //
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* </pre>
*/
public static class IPv6SegmentRoutingHeader extends IPv6RoutingHeader {
private final List<IPv6Address> addresses = new ArrayList<IPv6Address>();
private final List<IPv6SegmentRoutingTLV> tlvs = new ArrayList<IPv6SegmentRoutingTLV>();
@Override
public String toString() {
return "IPv6SegmentRoutingHeader [addresses=" + addresses + ", tlvs=" + tlvs + ", getLastEntry()="
+ getLastEntry() + ", getFlags()=" + getFlags() + ", getTag()=" + getTag() + ", getAddresses()="
+ getAddresses() + ", getRoutingType()=" + getRoutingType() + ", getSegmentsLeft()="
+ getSegmentsLeft() + ", getProtocolNumber()=" + getProtocolNumber() + ", getNextHeader()="
+ getNextHeader() + ", getExtLength()=" + getExtLength() + "]";
}
public IPv6SegmentRoutingHeader() {
super(EXT_HEADER_ALIGNMENT);
setRoutingType(SRV6_ROUTING_TYPE);
}
public IPv6SegmentRoutingHeader(ByteBuffer bbf) {
super(EXT_HEADER_ALIGNMENT, bbf);
}
public IPv6SegmentRoutingHeader(List<IPv6Address> segs) {
this();
this.addresses.addAll(segs);
resetSegmentPos();
}
public void resetSegmentPos() {
int ln = addresses.size() - 1;
setLastEntry(ln);
setSegmentsLeft(ln);
}
public int getLastEntry() {
return getData().get(4) & BIT_MASK_LOW_8_BITS;
}
public void setLastEntry(int lastEntry) {
getData().put(4, (byte) lastEntry);
}
public int getFlags() {
return getData().get(5) & BIT_MASK_LOW_8_BITS;
}
public void setFlags(int flags) {
getData().put(5, (byte) flags);
}
public int getTag() {
return getData().getShort(6) & BIT_MASK_LOW_16_BITS;
}
public void setTag(int tag) {
getData().putShort(6, (short) tag);
}
public List<IPv6Address> getAddresses() {
return addresses;
}
public List<IPv6SegmentRoutingTLV> getTlvs() {
return tlvs;
}
@Override
public void writeToChannel(WritableByteChannel dto) throws IOException {
int exl = calcExtLength();
if (exl % EXT_HEADER_ALIGNMENT != 0) {
throw new StreamCorruptedException("extLength % " + EXT_HEADER_ALIGNMENT + " !=0");
}
setExtLength(exl / EXT_HEADER_ALIGNMENT);
setLastEntry(addresses.size() - 1);
super.writeToChannel(dto);
ByteBuffer addr=NetworkPacket.bufferAllocator.allocateHeap(addresses.size() *IPV6_ADDRESS_LENGTH);
for (IPv6Address inet6Address : addresses) {
inet6Address.writeTo(addr);
}
addr.flip();
dto.write(addr);
for (IPv6SegmentRoutingTLV tlv : tlvs) {
IPv6SegmentRoutingTLV.writeIPv6SegmentRoutingTLVToChannel(dto, tlv);
}
}
private int calcExtLength() {
int tlvsl = 0;
for (IPv6SegmentRoutingTLV tlve : tlvs) {
tlvsl += tlve.getTotalLength();
}
return addresses.size() * IPV6_ADDRESS_LENGTH + tlvsl;
}
/*@Override
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
super.readFromChannel(din, length);
int extl = getExtLength();
int laste = getLastEntry();
int rl = extl * EXT_HEADER_ALIGNMENT;
int usdl = 0;
// System.out.println("SR length:"+(laste+1));
addresses.clear();
ByteBuffer bfr = NetworkPacket.bufferAllocator.allocateHeap(IPV6_ADDRESS_LENGTH);
for (int i = 0; i < (laste + 1); i++) {
bfr.clear();
while (bfr.hasRemaining()) {
if (din.read(bfr) == -1) {
throw new EOFException();
}
}
bfr.flip();
usdl += bfr.limit();
Inet6Address addr = (Inet6Address) Inet6Address.getByAddress(bfr.array());
// System.out.println("SR:"+addr);
addresses.add(addr);
}
tlvs.clear();
while (usdl < rl) {
IPv6SegmentRoutingTLV tlv = IPv6SegmentRoutingTLV.readIPv6SegmentRoutingTLVFromChannel(din);
usdl += tlv.getTotalLength();
tlvs.add(tlv);
}
return;
}*/
@Override
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
super.readFromChannel(din, length);
ByteBuffer bfr = null;
int extl = getExtLength();
int laste = getLastEntry();
int rl = extl * EXT_HEADER_ALIGNMENT;
int usdl = 0;
// 验证lastEntry的合理性
if (laste < 0 ) {
throw new StreamCorruptedException("Invalid lastEntry: " + laste);
}
addresses.clear();
bfr = NetworkPacket.bufferAllocator.allocateHeap(IPV6_ADDRESS_LENGTH*(laste+1));
KNEChannels.readFully(din, bfr);
bfr.flip();
usdl += bfr.limit();
for (int i = 0; i <= laste; i++) { // 注意:应该是 <= laste
addresses.add(IPv6Address.valueOf(bfr));
}
tlvs.clear();
while (usdl < rl) {
IPv6SegmentRoutingTLV tlv = IPv6SegmentRoutingTLV.readIPv6SegmentRoutingTLVFromChannel(din);
usdl += tlv.getTotalLength();
tlvs.add(tlv);
}
// 验证读取的字节数与预期一致
if (usdl != rl) {
throw new StreamCorruptedException("Length mismatch: expected " + rl + ", got " + usdl);
}
}
// 辅助方法:确保读取完整数据
private int readFully(ReadableByteChannel channel, ByteBuffer buffer) throws IOException {
int totalRead = 0;
while (buffer.hasRemaining()) {
int read = channel.read(buffer);
if (read == -1) {
break;
}
totalRead += read;
}
return totalRead;
}
@Override
public long getTotalLength() {
return calcExtLength() + EXT_HEADER_ALIGNMENT;
}
}
/**
* IPv6目标选项头部类
*/
public static class IPv6DestinationHeader extends IPv6ExtHeader {
@Override
public String toString() {
return "IPv6DestinationHeader [protocolNumber=" + getProtocolNumber() + ", getNextHeader()="
+ getNextHeader() + ", getExtLength()=" + getExtLength() + ", getRoutingType()=" + getRoutingType()
+ "]";
}
public IPv6DestinationHeader() {
super(DESTINATION_OPTIONS);
}
public int getRoutingType() {
return getData().get(2) & BIT_MASK_LOW_8_BITS;
}
public void setRoutingType(int routingTypr) {
getData().put(2, (byte) routingTypr);
}
public int getSegmentsLeft() {
return getData().get(3);
}
public void setSegmentsLeft(int segmentsLeft) {
getData().put(3, (byte) segmentsLeft);
}
}
/**
* 获取所有扩展头部
* @return 扩展头部列表
*/
public List<IPv6ExtHeader> getHeaders() {
return headers;
}
/**
* 获取IPv6逐跳头部
* @return IPv6段逐跳头部,如果不存在则返回null
*/
public IPv6HopByHopHeader getHopByHopHeader() {
return hopByHopHeader;
}
/**
* 获取路由头部
* @return 路由头部,如果不存在则返回null
*/
public IPv6RoutingHeader getRoutingHeader() {
return routingHeader;
}
public void setHopByHopHeader(IPv6HopByHopHeader hopByHopHeader) {
this.hopByHopHeader = hopByHopHeader;
}
public void setRoutingHeader(IPv6RoutingHeader routingHeader) {
this.routingHeader = routingHeader;
}
/**
* 获取SRv6段路由头部
* @return SRv6段路由头部,如果不存在则返回null
*/
public IPv6SegmentRoutingHeader getSegmentRoutingHeader() {
IPv6RoutingHeader rh=getRoutingHeader();
if(rh==null)
return null;
IPv6SegmentRoutingHeader srhh=null;
if (rh instanceof IPv6SegmentRoutingHeader) {
if (((IPv6SegmentRoutingHeader) rh).getRoutingType() == SRV6_ROUTING_TYPE) {
srhh = (IPv6SegmentRoutingHeader) rh;
}
}
return srhh;
}
public UUID getPacketID() {
IPv6HopByHopHeader hop=getHopByHopHeader();
if(hop==null)
return null;
List<IPv6HopByHopTLV> tlvs= hop.getTlvs();
for(IPv6HopByHopTLV tlv:tlvs) {
if(tlv instanceof KLALBOAMHopByHopTLV)
return ((KLALBOAMHopByHopTLV)tlv).getUUID();
}
return null;
}
@Override
protected boolean needEndPosition() {
return false;
}
// 重路由计数器
private AtomicInteger rerouteCounter = new AtomicInteger(0);
public AtomicInteger getRerouteCounter() {
return rerouteCounter;
}
public long calculateAddressChecksum() {
long sum=0;
ByteBuffer dataCopy = IPv6header.slice(SOURCE_ADDRESS_OFFSET,32);
while (dataCopy.remaining() >= 2) {
sum += dataCopy.getChar();
}
if (dataCopy.remaining() == 1) {
sum += (dataCopy.get() & 0xFF) << 8;
}
return sum;
}
}