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

841 lines
22 KiB
Java

package org.kne.cloud.network.ipv6;
import java.io.EOFException;
import java.io.IOException;
import java.net.Inet6Address;
import java.net.InetAddress;
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.Iterator;
import java.util.List;
import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6ExtHeader;
import org.kne.cloud.network.klalb.KLALBPacket;
import org.kne.cloud.network.srv6.IPv6SegmentRoutingTLV;
import org.kne.cloud.network.srv6.IpV6RoutingSRHData;
import org.kne.cloud.network.srv6.SRv6Pad1TLV;
import org.kne.cloud.network.srv6.SRv6PadNTLV;
import org.kne.cloud.network.srv6.SRv6StreamSequenceTLV;
import org.kne.cloud.network.srv6.SRv6TLV;
import org.pcap4j.packet.namednumber.IpNumber;
public class IPv6Packet extends NetworkPacket {
private volatile ByteBuffer IPv6header ;
private volatile List<IPv6ExtHeader> headers = new ArrayList<>();
private IPv6Payload payload;
public static final int IPv6_HEADER_LENGTH = 40;
public IPv6Payload getPayload() {
return payload;
}
public void setPayload(IPv6Payload payload) {
this.payload = payload;
}
public IPv6Packet() {
IPv6header = NetworkPacket.databufferpool_40.borrow();
IPv6header.limit(IPv6_HEADER_LENGTH);
}
public static int getIPVersion(byte b) {
return b>>>4;
}
public int getVersion() {
return IPv6header.get(0) >>> 4;
}
public void setVersion(int version) {
IPv6header.put(0, (byte) (IPv6header.get(0) & 0b00001111 | version << 4));
}
public int getTrafficClass() {
return (IPv6header.get(0) << 4) & (IPv6header.get(1) >>> 4) & 0xff;
}
public void setTrafficClass(int trafficClass) {
IPv6header.put(0, (byte) (IPv6header.get(0) & 0b11110000 | (trafficClass >>> 4)));
IPv6header.put(1, (byte) (IPv6header.get(1) & 0b00001111 | ((trafficClass & 0b00001111) << 4)));
}
public boolean isEnableECN() {
return (IPv6header.get(1)&0b00110000)!=0;
}
public void enableECN() {
IPv6header.put(1, (byte) ((IPv6header.get(1)&0b11101111)|0b00100000));
}
public void markCE() {
IPv6header.put(1,(byte) (IPv6header.get(1)|0b00110000));
}
public boolean isCE() {
return ((IPv6header.get(1)>>>4)&0b11)==0b11;
}
public int getFlowLabel() {
return ((IPv6header.get(1) & 0b00001111) << 16) | (IPv6header.getShort(2) & 0xffff);
}
public void setFlowLabel(int flowLabel) {
IPv6header.put(1, (byte) (IPv6header.get(1) & 0b11110000 | (flowLabel >>> 16)));
IPv6header.putShort(2, (short) flowLabel);
}
public int getPayloadLength() {
return IPv6header.getShort(4) & 0xffff;
}
public void setPayloadLength(int payloadLength) {
IPv6header.putShort(4, (short) payloadLength);
}
public int getNextHeader() {
return IPv6header.get(6) & 0xff;
}
public void setNextHeader(int nextHeader) {
IPv6header.put(6, (byte) nextHeader);
}
public int getHopLimit() {
return IPv6header.get(7) & 0xff;
}
public void setHopLimit(int hopLimit) {
IPv6header.put(7, (byte) hopLimit);
}
public Inet6Address getSourceAddress() {
byte[] b = new byte[16];
IPv6header.get(8, b, 0, b.length);
try {
return (Inet6Address) Inet6Address.getByAddress(b);
} catch (UnknownHostException e) {
return null;
}
}
public void setSourceAddress(Inet6Address sourceAddress) {
byte[] b = sourceAddress.getAddress();
IPv6header.put(8, b, 0, b.length);
}
public Inet6Address getDestinationAddress() {
byte[] b = new byte[16];
IPv6header.get(24, b, 0, b.length);
try {
return (Inet6Address) Inet6Address.getByAddress(b);
} catch (UnknownHostException e) {
return null;
}
}
public void setDestinationAddress(Inet6Address destinationAddress) {
byte[] b = destinationAddress.getAddress();
IPv6header.put(24, b, 0, b.length);
}
public FlowSession getFlowSession() {
return new FlowSession(getSourceAddress(), getDestinationAddress(), getFlowLabel());
}
private int calcPayloadLength() {
int lth=0;
for (int i = 0; i < headers.size(); i++) {
lth+= headers.get(i).getLength();
}
lth+=payload.getLength();
return lth;
}
@Override
public long getLength() {
return calcPayloadLength()+IPv6_HEADER_LENGTH;
}
@Override
public void doDisposeAfterSend() {
super.doDisposeAfterSend();
payload.doDisposeAfterSend();
}
@Override
public void dispose() {
super.dispose();
/*ByteBuffer headerx = IPv6header;
IPv6header = null;
if(headerx!=null)
NetworkPacket.databufferpool_40.back(headerx);*/
}
@Override
public void disposeAll() {
super.disposeAll();
for (int i = 0; i < headers.size(); i++) {
headers.get(i).disposeAll();
}
payload.disposeAll();
}
@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);
}
@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 0:
ext=new IPv6ExtHeader(nextheader);
ext.readFromChannel(din, 0);
nextheader=ext.getNextHeader();
payloadlength-=ext.getLength();
headers.add(ext);
break;
case 60:
ext=new IPv6DestinationHeader();
ext.readFromChannel(din, 0);
nextheader=ext.getNextHeader();
payloadlength-=ext.getLength();
headers.add(ext);
break;
case 43:
ByteBuffer bbf=NetworkPacket.databufferpool_2048.borrow();
bbf.limit(4);
while (bbf.hasRemaining()) {
if (din.read(bbf) == -1) {
throw new EOFException();
}
}
int routingType= bbf.get(2)&0xff;
switch(routingType) {
case 4:
ext=new IPv6SegmentRoutingHeader(bbf);
break;
default:
ext=new IPv6RoutingHeader(true,bbf);
break;
}
ext.readFromChannel(din, 0);
nextheader=ext.getNextHeader();
payloadlength-=ext.getLength();
headers.add(ext);
break;
case 44:
ext=new IPv6ExtHeader(nextheader);
ext.readFromChannel(din, 0);
nextheader=ext.getNextHeader();
payloadlength-=ext.getLength();
headers.add(ext);
break;
case 50:
ext=new IPv6ExtHeader(nextheader);
ext.readFromChannel(din, 0);
nextheader=ext.getNextHeader();
payloadlength-=ext.getLength();
headers.add(ext);
break;
case 51:
ext=new IPv6ExtHeader(nextheader);
ext.readFromChannel(din, 0);
nextheader=ext.getNextHeader();
payloadlength-=ext.getLength();
headers.add(ext);
break;
case 59:
ext=new IPv6ExtHeader(nextheader);
ext.readFromChannel(din, 0);
nextheader=ext.getNextHeader();
payloadlength-=ext.getLength();
headers.add(ext);
break;
case KLALBPacket.KLALB_PROTOCOL_NUMBER:
KLALBPacket kp=KLALBPacket.readKLALBPacketFromChannel(din);
this.payload=kp;
break loop;
default:
IPv6Payload pld=new IPv6Payload(nextheader);
pld.readFromChannel(din, payloadlength);
this.payload=pld;
break loop;
}
}
}
/*public void analyse() {
headers.clear();
int headerPos=IPv6_HEADER_LENGTH;
int nextheader=getNextHeader();
int payloadlength=getPayloadLength();
loop: while(true) {
IPv6ExtHeader ext;
switch(nextheader) {
case 0:
ext=new IPv6ExtHeader(headerPos,nextheader);
nextheader=ext.getNextHeader();
payloadlength-=ext.getLength();
headerPos+=ext.getLength();
headers.add(ext);
break;
case 60:
ext=new IPv6DestinationHeader(headerPos);
nextheader=ext.getNextHeader();
payloadlength-=ext.getLength();
headerPos+=ext.getLength();
headers.add(ext);
break;
case 43:
ext=new IPv6RoutingHeader(headerPos);
nextheader=ext.getNextHeader();
payloadlength-=ext.getLength();
headerPos+=ext.getLength();
headers.add(ext);
break;
case 44:
ext=new IPv6ExtHeader(headerPos,nextheader);
nextheader=ext.getNextHeader();
payloadlength-=ext.getLength();
headerPos+=ext.getLength();
headers.add(ext);
break;
case 50:
ext=new IPv6ExtHeader(headerPos,nextheader);
nextheader=ext.getNextHeader();
payloadlength-=ext.getLength();
headerPos+=ext.getLength();
headers.add(ext);
break;
case 51:
ext=new IPv6ExtHeader(headerPos,nextheader);
nextheader=ext.getNextHeader();
payloadlength-=ext.getLength();
headerPos+=ext.getLength();
headers.add(ext);
break;
case 59:
ext=new IPv6ExtHeader(headerPos,nextheader);
nextheader=ext.getNextHeader();
payloadlength-=ext.getLength();
headerPos+=ext.getLength();
headers.add(ext);
break;
default:
IPv6Payload pld=new IPv6Payload(headerPos,payloadlength,nextheader);
this.payload=pld;
break loop;
}
}
//System.out.println(headers);
//System.out.println(payload);
}*/
@Override
public void lockAll() {
super.lockAll();
for (int i = 0; i < headers.size(); i++) {
headers.get(i).lockAll();
}
payload.lockAll();
}
@Override
public boolean isSomeDisposed() {
if(super.isSomeDisposed()||payload.isSomeDisposed())
return true;
for (Iterator<IPv6ExtHeader> iterator = headers.iterator(); iterator.hasNext();) {
IPv6ExtHeader iPv6ExtHeader = (IPv6ExtHeader) iterator.next();
if(iPv6ExtHeader.isSomeDisposed())
return true;
}
return false;
}
@Override
public void unlockAll() {
payload.unlockAll();
for (int i = 0; i < headers.size(); i++) {
headers.get(i).unlockAll();
}
super.unlockAll();
}
@Override
public String toString() {
return "IPv6Packet [getVersion()=" + getVersion() + ", getTrafficClass()=" + getTrafficClass()
+ ", getFlowLabel()=" + getFlowLabel() + ", getPayloadLength()=" + getPayloadLength()
+ ", getNextHeader()=" + getNextHeader() + ", getHopLimit()=" + getHopLimit() + ", getSourceAddress()="
+ getSourceAddress() + ", getDestinationAddress()=" + getDestinationAddress() + ", getLength()="
+ getLength() + ", headers=" + headers + ", payload=" + payload + "]";
}
public static class IPv6Payload extends NetworkPacket{
private ByteBuffer data ;
private boolean onDefault=true;
public ByteBuffer getData() {
return data;
}
private int protocolNumber;
public IPv6Payload(int protocolNumber) {
this(protocolNumber,true);
}
protected IPv6Payload(int protocolNumber,boolean isonDefault) {
this.protocolNumber = protocolNumber;
this.onDefault=isonDefault;
if(onDefault)
this.data=NetworkPacket.databufferpool_65535.borrow();
}
public int getProtocolNumber() {
return protocolNumber;
}
public long getLength() {
return data.limit();
}
@Override
protected void writeToChannel(WritableByteChannel dto) throws IOException {
if(onDefault)
dto.write(data.slice(0,data.limit()));
}
@Override
protected void readFromChannel(ReadableByteChannel din, long length) throws IOException {
if(onDefault) {
data.limit((int) length);
while (data.hasRemaining()) {
if (din.read(data) == -1) {
throw new EOFException();
}
}
}
}
@Override
public void dispose() {
super.dispose();
/*if(onDefault) {
ByteBuffer datax = data;
data = null;
NetworkPacket.databufferpool_65535.back(datax);
}*/
}
@Override
protected boolean needEndPosition() {
return true;
}
}
public static class IPv6ExtHeader extends NetworkPacket{
private ByteBuffer data ;
private int protocolNumber;
private boolean onDefault=true;
@Override
public String toString() {
return "IPv6ExtHeader [protocolNumber=" + protocolNumber + ", getNextHeader()=" + getNextHeader()
+ ", getExtLength()=" + getExtLength() + "]";
}
public ByteBuffer getData() {
return data;
}
public IPv6ExtHeader(int type) {
this(type,true);
}
protected IPv6ExtHeader(int protocolNumber,boolean isonDefault) {
this.protocolNumber = protocolNumber;
this.onDefault=isonDefault;
if(onDefault) {
this.data=NetworkPacket.databufferpool_2048.borrow();
}else {
this.data=NetworkPacket.databufferpool_40.borrow();
}
}
protected IPv6ExtHeader(int protocolNumber,boolean isonDefault,ByteBuffer data) {
this.protocolNumber = protocolNumber;
this.onDefault=isonDefault;
this.data=data;
}
public int getProtocolNumber() {
return protocolNumber;
}
public int getNextHeader() {
return data.get(0) & 0xff;
}
public void setNextHeader(int nextHeader) {
data.put(0, (byte) nextHeader);
}
public int getExtLength() {
return data.get(1) & 0xff;
}
protected void setExtLength(int extLength) {
data.put(1, (byte) extLength);
}
public long getLength() {
return data.limit();
}
@Override
protected void writeToChannel(WritableByteChannel dto) throws IOException {
if(onDefault) {
int ext=(data.limit()-8)/8;
setExtLength(ext);
dto.write(data.slice(0,data.limit()));
}else {
dto.write(data.slice(0,8));
}
}
@Override
protected void readFromChannel(ReadableByteChannel din, long length) throws IOException {
data.limit(8);
while (data.hasRemaining()) {
if (din.read(data) == -1) {
throw new EOFException();
}
}
if(onDefault) {
int newLimit=getExtLength()*8+data.limit();
data.limit(newLimit);
while (data.hasRemaining()) {
if (din.read(data) == -1) {
throw new EOFException();
}
}
}
}
@Override
protected boolean needEndPosition() {
return false;
}
@Override
public void dispose() {
super.dispose();
/*ByteBuffer bbft=data;
data=null;
if(bbft!=null) {
if(bbft.capacity()==40) {
NetworkPacket.databufferpool_40.back(bbft);
}else {
NetworkPacket.databufferpool_2048.back(bbft);
}
}*/
}
}
public static class IPv6RoutingHeader extends IPv6ExtHeader{
@Override
public String toString() {
return "IPv6RoutingHeader [protocolNumber=" + getProtocolNumber() + ", getNextHeader()=" + getNextHeader()
+ ", getExtLength()=" + getExtLength()+ ", getRoutingType()="+getRoutingType() + "]";
}
public IPv6RoutingHeader() {
super(43);
}
public IPv6RoutingHeader(boolean onDefault) {
super(43,onDefault);
}
public IPv6RoutingHeader( boolean isonDefault, ByteBuffer data) {
super(43, isonDefault, data);
}
public int getRoutingType() {
return getData().get(2)&0xff;
}
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);
}
}
public static class IPv6SegmentRoutingHeader extends IPv6RoutingHeader{
private final List<Inet6Address> addresses=new ArrayList<Inet6Address>();
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(false);
setRoutingType(4);
}
public IPv6SegmentRoutingHeader(ByteBuffer bbf) {
super(false,bbf);
}
public IPv6SegmentRoutingHeader(List<Inet6Address> segs) {
this();
this.addresses.addAll( segs);
int ln=addresses.size()-1;
setLastEntry(ln);
setSegmentsLeft(ln);
}
public int getLastEntry() {
return getData().get(4)&0xff;
}
public void setLastEntry(int lastEntry) {
getData().put(4, (byte) lastEntry);
}
public int getFlags() {
return getData().get(5)&0xff;
}
public void setFlags(int flags) {
getData().put(5,(byte) flags);
}
public int getTag() {
return getData().getShort(6)&0xffff;
}
public void setTag(int tag) {
getData().putShort(6,(short) tag);
}
public List<Inet6Address> getAddresses() {
return addresses;
}
@Override
protected void writeToChannel(WritableByteChannel dto) throws IOException {
setExtLength(calcExtLength()/8);
setLastEntry(addresses.size()-1);
super.writeToChannel(dto);
for (Iterator<Inet6Address> iterator = addresses.iterator(); iterator.hasNext();) {
Inet6Address inet6Address = (Inet6Address) iterator.next();
dto.write(ByteBuffer.wrap(inet6Address.getAddress()));
}
}
private int calcExtLength() {
int tlvsl=0;
for (Iterator<IPv6SegmentRoutingTLV> iterator = tlvs.iterator(); iterator.hasNext();) {
IPv6SegmentRoutingTLV tlve = (IPv6SegmentRoutingTLV) iterator.next();
tlvsl+=tlve.getLength();
}
return addresses.size()*16+tlvsl;
}
@Override
protected void readFromChannel(ReadableByteChannel din, long length) throws IOException {
super.readFromChannel(din, length);
int extl=getExtLength();
int laste=getLastEntry();
int rl=extl*8;
int usdl=0;
//System.out.println("SR length:"+(laste+1));
addresses.clear();
ByteBuffer bfr=ByteBuffer.allocate(16);
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);
}
return;
}
@Override
public long getLength() {
return calcExtLength()+8;
}
}
public static class IPv6DestinationHeader extends IPv6ExtHeader{
@Override
public String toString() {
return "IPv6DestinationHeader [protocolNumber=" + getProtocolNumber() + ", getNextHeader()=" + getNextHeader()
+ ", getExtLength()=" + getExtLength()+ ", getRoutingType()="+getRoutingType() + "]";
}
public IPv6DestinationHeader() {
super( 60);
}
public int getRoutingType() {
return getData().get(2)&0xff;
}
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);
}
}
public List<IPv6ExtHeader> getHeaders() {
return headers;
}
/*public IPv6DestinationHeader insertDestinationHeader(int index,int extLength) {
long ptr;
long lth=extLength*8+8;
if(index==headers.size()) {
ptr=payload.getPointer();
}else if(index<headers.size()){
IPv6ExtHeader iext=headers.get(index);
ptr=iext.getPointer();
}else {
throw new IndexOutOfBoundsException(index);
}
byte[]temp=new byte[(int) (IPv6data.limit()-ptr)];
IPv6data.get((int) ptr, temp);
IPv6data.limit((int) (IPv6data.limit()+lth));
setPayloadLength((int) (getPayloadLength()+lth));
IPv6data.put((int) (ptr+lth), temp);
IPv6DestinationHeader irh=new IPv6DestinationHeader(ptr,extLength);
if(index>=headers.size()) {
irh.setNextHeader(payload.getType());
}else {
irh.setNextHeader(headers.get(index).getType());
}
if(index-1<0) {
setNextHeader(irh.getType());
}else {
headers.get(index-1).setNextHeader(irh.getType());
}
headers.add(index, irh);
analyse();
return irh;
}
public IPv6RoutingHeader insertSRHRoutingHeader(int index,IpV6RoutingSRHData srh) {
long ptr;
long lth=srh.length()+4;
if(index==headers.size()) {
ptr=payload.getPointer();
}else if(index<headers.size()){
IPv6ExtHeader iext=headers.get(index);
ptr=iext.getPointer();
}else {
throw new IndexOutOfBoundsException(index);
}
byte[]temp=new byte[(int) (IPv6data.limit()-ptr)];
IPv6data.get((int) ptr, temp);
IPv6data.limit((int) (IPv6data.limit()+lth));
setPayloadLength((int) (getPayloadLength()+lth));
IPv6data.put((int) (ptr+lth), temp);
IPv6RoutingHeader irh=new IPv6RoutingHeader(ptr,(int) ((lth-8)/8));
if(index>=headers.size()) {
irh.setNextHeader(payload.getType());
}else {
irh.setNextHeader(headers.get(index).getType());
}
if(index-1<0) {
setNextHeader(irh.getType());
}else {
headers.get(index-1).setNextHeader(irh.getType());
}
headers.add(index, irh);
irh.setRoutingType(4);
irh.setSegmentsLeft(srh.getLastEntry());
irh.getData().put(4, srh.getRawData());
analyse();
return irh;
}*/
@Override
protected boolean needEndPosition() {
return false;
}
}