diff options
author | Mikael Magnusson <mikma@users.sourceforge.net> | 2022-01-30 14:49:42 +0100 |
---|---|---|
committer | Mikael Magnusson <mikma@users.sourceforge.net> | 2023-11-13 00:17:57 +0100 |
commit | d4eb9c36754afcfbfbf758afd80816ee71a57362 (patch) | |
tree | 5b5a0b658035bc9cef2f8058616f4f351370364f | |
parent | 45143e7d7ad17e149d4df8f5502a15c3222691e4 (diff) |
WIP multiprotocol capability and IPv6
7 files changed, 160 insertions, 2 deletions
diff --git a/src/main/java/com/lumaserv/bgp/protocol/AFI.java b/src/main/java/com/lumaserv/bgp/protocol/AFI.java new file mode 100644 index 0000000..1dce43b --- /dev/null +++ b/src/main/java/com/lumaserv/bgp/protocol/AFI.java @@ -0,0 +1,21 @@ +package com.lumaserv.bgp.protocol; + +import java.util.EnumSet; + +import lombok.Getter; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +@Getter +public enum AFI { + IPV4(1, "IPv4"), + IPV6(2, "IPv6"); + + int value; + String desc; + + public static AFI fromInteger(int value) { + return EnumSet.allOf(AFI.class).stream().filter(e -> e.getValue() == value).findAny().orElseThrow( + () -> new IllegalArgumentException("unknown address family: " + value)); + } +} diff --git a/src/main/java/com/lumaserv/bgp/protocol/IPPrefix.java b/src/main/java/com/lumaserv/bgp/protocol/IPPrefix.java index be70c4f..f68677c 100644 --- a/src/main/java/com/lumaserv/bgp/protocol/IPPrefix.java +++ b/src/main/java/com/lumaserv/bgp/protocol/IPPrefix.java @@ -13,7 +13,7 @@ import java.net.UnknownHostException; public class IPPrefix { byte[] address; - byte length; + int length; public String toString() { try { diff --git a/src/main/java/com/lumaserv/bgp/protocol/SAFI.java b/src/main/java/com/lumaserv/bgp/protocol/SAFI.java new file mode 100644 index 0000000..5fa6b99 --- /dev/null +++ b/src/main/java/com/lumaserv/bgp/protocol/SAFI.java @@ -0,0 +1,21 @@ +package com.lumaserv.bgp.protocol; + +import java.util.EnumSet; + +import lombok.Getter; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +@Getter +public enum SAFI { + UNICAST(1, "NLRI Unicast"), + MULTICAST(2, "NLRI Multicast"); + + int value; + String desc; + + public static SAFI fromInteger(int value) { + return EnumSet.allOf(SAFI.class).stream().filter(e -> e.getValue() == value).findAny().orElseThrow( + () -> new IllegalArgumentException("unknown subsequent address family: " + value)); + } +} diff --git a/src/main/java/com/lumaserv/bgp/protocol/attribute/MPReachableNLRIAttribute.java b/src/main/java/com/lumaserv/bgp/protocol/attribute/MPReachableNLRIAttribute.java new file mode 100644 index 0000000..346cb0e --- /dev/null +++ b/src/main/java/com/lumaserv/bgp/protocol/attribute/MPReachableNLRIAttribute.java @@ -0,0 +1,59 @@ +package com.lumaserv.bgp.protocol.attribute; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collection; + +import lombok.Getter; +import lombok.Setter; + +import com.lumaserv.bgp.protocol.AFI; +import com.lumaserv.bgp.protocol.IPPrefix; +import com.lumaserv.bgp.protocol.SAFI; + +@Getter +@Setter +public class MPReachableNLRIAttribute implements PathAttribute { + + AFI afi; + SAFI safi; + byte[] nextHop; + Collection<IPPrefix> nlriPrefixes; + + public MPReachableNLRIAttribute(byte typeCode, byte[] data) { + afi = AFI.fromInteger((data[0] << 8) | data[1]); + safi = SAFI.fromInteger(data[2]); + int nhLen = data[3]; + nextHop = new byte[nhLen]; + System.arraycopy(data, 4, nextHop, 0, nextHop.length); + int nlriLen = data.length - 5 - nhLen; + nlriPrefixes = new ArrayList<>(); + + int offset = 4 + nhLen + 1; + int offsetOffset = offset; + while ((offset - offsetOffset) < nlriLen) { + IPPrefix prefix = new IPPrefix() + .setLength((int)(data[offset]&0xff)) // FIXME IPv4/IPv6 etc + .setAddress(new byte[16]); + offset++; + int addressLen = (int) Math.ceil(prefix.getLength() / 8d); + System.arraycopy(data, offset, prefix.getAddress(), 0, addressLen); + offset += addressLen; + nlriPrefixes.add(prefix); + } + } + + public byte getTypeCode() { + return 14; + } + + public void build(ByteBuffer b) { + // FIXME + } + + public String toString() { + return "AFI:" + afi + " SAFI:" + safi + " NLRIs:" + nlriPrefixes; + } +} diff --git a/src/main/java/com/lumaserv/bgp/protocol/attribute/MPUnreachableNLRIAttribute.java b/src/main/java/com/lumaserv/bgp/protocol/attribute/MPUnreachableNLRIAttribute.java new file mode 100644 index 0000000..43dc8d5 --- /dev/null +++ b/src/main/java/com/lumaserv/bgp/protocol/attribute/MPUnreachableNLRIAttribute.java @@ -0,0 +1,36 @@ +package com.lumaserv.bgp.protocol.attribute; + +import lombok.Getter; +import lombok.Setter; + +import com.lumaserv.bgp.protocol.AFI; +import com.lumaserv.bgp.protocol.SAFI; + +import java.nio.ByteBuffer; + +@Getter +@Setter +public class MPUnreachableNLRIAttribute implements PathAttribute { + + AFI afi; + SAFI safi; + int nlriLen; + + public MPUnreachableNLRIAttribute(byte typeCode, byte[] data) { + afi = AFI.fromInteger((data[0] << 8) | data[1]); + safi = SAFI.fromInteger(data[2]); + nlriLen = data.length - 3; + } + + public byte getTypeCode() { + return 15; + } + + public void build(ByteBuffer b) { + // FIXME + } + + public String toString() { + return "AFI:" + afi + " SAFI:" + safi + " NLRIs:" + nlriLen; + } +} diff --git a/src/main/java/com/lumaserv/bgp/protocol/attribute/PathAttribute.java b/src/main/java/com/lumaserv/bgp/protocol/attribute/PathAttribute.java index 95156ed..117a147 100644 --- a/src/main/java/com/lumaserv/bgp/protocol/attribute/PathAttribute.java +++ b/src/main/java/com/lumaserv/bgp/protocol/attribute/PathAttribute.java @@ -21,6 +21,10 @@ public interface PathAttribute { return new AggregatorAttribute(typeCode, data); case 8: return new CommunitiesAttribute(typeCode, data); + case 14: + return new MPReachableNLRIAttribute(typeCode, data); + case 15: + return new MPUnreachableNLRIAttribute(typeCode, data); case 16: return new ExtendedCommuntiesAttribute(typeCode, data); case 17: diff --git a/src/main/java/com/lumaserv/bgp/protocol/message/BGPOpen.java b/src/main/java/com/lumaserv/bgp/protocol/message/BGPOpen.java index 875f7bc..e83b751 100644 --- a/src/main/java/com/lumaserv/bgp/protocol/message/BGPOpen.java +++ b/src/main/java/com/lumaserv/bgp/protocol/message/BGPOpen.java @@ -22,13 +22,30 @@ public class BGPOpen { } public byte[] build() { - byte[] message = new byte[6 + identifier.length]; + byte[] message = new byte[5 + identifier.length + 1 + 2 + 2 * 6]; message[0] = version; message[1] = (byte) (asn >> 8); message[2] = (byte) (asn & 0xFF); message[3] = (byte) (holdTime >> 8); message[4] = (byte) (holdTime & 0xFF); System.arraycopy(identifier, 0, message, 5, identifier.length); + message[5 + identifier.length + 0] = 14; // Length (0E) + message[5 + identifier.length + 1] = 2; // Parameter Type: capability (02) + message[5 + identifier.length + 2] = 12; // Length (0C) + + message[5 + identifier.length + 3] = 1; // Type: multiprotocol (01) + message[5 + identifier.length + 4] = 4; // Length (04) + message[5 + identifier.length + 5] = 0; // IPv6 (0002) + message[5 + identifier.length + 6] = 2; // + message[5 + identifier.length + 7] = 0; // Reserved + message[5 + identifier.length + 8] = 1; // Unicast (01) + + message[5 + identifier.length + 9] = 1; // Type: multiprotocol (01) + message[5 + identifier.length +10] = 4; // Length (04) + message[5 + identifier.length +11] = 0; // IPv4 (0001) + message[5 + identifier.length +12] = 1; // + message[5 + identifier.length +13] = 0; // Reserved + message[5 + identifier.length +14] = 1; // Unicast (01) return message; } |