From 910744394f2529ecac0fa91a16237777e023c5e6 Mon Sep 17 00:00:00 2001 From: Kris Michielsen Date: Thu, 22 Jun 2017 13:00:20 +0200 Subject: SRv6 tests Change-Id: Ib1d2fc5a83d9d007a0468591a73881675f1bec9b Signed-off-by: Kris Michielsen --- test/patches/scapy-2.3.3/inet6.py.patch | 185 ++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 test/patches/scapy-2.3.3/inet6.py.patch (limited to 'test/patches/scapy-2.3.3/inet6.py.patch') diff --git a/test/patches/scapy-2.3.3/inet6.py.patch b/test/patches/scapy-2.3.3/inet6.py.patch new file mode 100644 index 00000000..f98e7091 --- /dev/null +++ b/test/patches/scapy-2.3.3/inet6.py.patch @@ -0,0 +1,185 @@ +diff --git a/scapy/layers/inet6.py b/scapy/layers/inet6.py +--- a/scapy/layers/inet6.py 2017-06-01 14:04:18.160881034 +0200 ++++ b/scapy/layers/inet6.py 2017-06-02 09:08:40.133800208 +0200 +@@ -369,6 +369,8 @@ + return Raw + elif self.nh == 135 and len(p) > 3: # Mobile IPv6 + return _mip6_mhtype2cls.get(ord(p[2]), MIP6MH_Generic) ++ elif self.nh == 43 and ord(p[2]) == 4: # Segment Routing header ++ return IPv6ExtHdrSegmentRouting + else: + return get_cls(ipv6nhcls.get(self.nh,"Raw"), "Raw") + +@@ -430,6 +432,14 @@ + sd = strxor(sd, a) + sd = inet_ntop(socket.AF_INET6, sd) + ++ if self.nh == 43 and isinstance(self.payload, IPv6ExtHdrSegmentRouting): ++ # With segment routing header (rh == 4), the destination is ++ # the first address of the IPv6 addresses list ++ try: ++ sd = self.addresses[0] ++ except IndexError: ++ sd = self.dst ++ + if self.nh == 44 and isinstance(self.payload, IPv6ExtHdrFragment): + nh = self.payload.nh + +@@ -489,6 +499,8 @@ + return self.payload.answers(other.payload.payload) + elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrRouting): + return self.payload.answers(other.payload.payload) # Buggy if self.payload is a IPv6ExtHdrRouting ++ elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrSegmentRouting): ++ return self.payload.answers(other.payload.payload) # Buggy if self.payload is a IPv6ExtHdrRouting + elif other.nh == 60 and isinstance(other.payload, IPv6ExtHdrDestOpt): + return self.payload.payload.answers(other.payload.payload) + elif self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt): # BU in reply to BRR, for instance +@@ -919,6 +931,148 @@ + pkt = pkt[:3]+struct.pack("B", len(self.addresses))+pkt[4:] + return _IPv6ExtHdr.post_build(self, pkt, pay) + ++######################### Segment Routing Header ############################ ++ ++# This implementation is based on draft 06, available at: ++# https://tools.ietf.org/html/draft-ietf-6man-segment-routing-header-06 ++ ++class IPv6ExtHdrSegmentRoutingTLV(Packet): ++ name = "IPv6 Option Header Segment Routing - Generic TLV" ++ fields_desc = [ ByteField("type", 0), ++ ByteField("len", 0), ++ ByteField("reserved", 0), ++ ByteField("flags", 0), ++ StrLenField("value", "", length_from=lambda pkt: pkt.len) ] ++ ++ def extract_padding(self, p): ++ return "",p ++ ++ registered_sr_tlv = {} ++ @classmethod ++ def register_variant(cls): ++ cls.registered_sr_tlv[cls.type.default] = cls ++ ++ @classmethod ++ def dispatch_hook(cls, pkt=None, *args, **kargs): ++ if pkt: ++ tmp_type = ord(pkt[0]) ++ return cls.registered_sr_tlv.get(tmp_type, cls) ++ return cls ++ ++ ++class IPv6ExtHdrSegmentRoutingTLVIngressNode(IPv6ExtHdrSegmentRoutingTLV): ++ name = "IPv6 Option Header Segment Routing - Ingress Node TLV" ++ fields_desc = [ ByteField("type", 1), ++ ByteField("len", 18), ++ ByteField("reserved", 0), ++ ByteField("flags", 0), ++ IP6Field("ingress_node", "::1") ] ++ ++ ++class IPv6ExtHdrSegmentRoutingTLVEgressNode(IPv6ExtHdrSegmentRoutingTLV): ++ name = "IPv6 Option Header Segment Routing - Egress Node TLV" ++ fields_desc = [ ByteField("type", 2), ++ ByteField("len", 18), ++ ByteField("reserved", 0), ++ ByteField("flags", 0), ++ IP6Field("egress_node", "::1") ] ++ ++ ++class IPv6ExtHdrSegmentRoutingTLVPadding(IPv6ExtHdrSegmentRoutingTLV): ++ name = "IPv6 Option Header Segment Routing - Padding TLV" ++ fields_desc = [ ByteField("type", 4), ++ FieldLenField("len", None, length_of="padding", fmt="B"), ++ StrLenField("padding", b"\x00", length_from=lambda pkt: pkt.len) ] ++ ++ ++class IPv6ExtHdrSegmentRouting(_IPv6ExtHdr): ++ # 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 bits IPv6 address) | ++ #| | ++ #| | ++ #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ #| | ++ #| | ++ # ... ++ #| | ++ #| | ++ #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ #| | ++ #| Segment List[n] (128 bits IPv6 address) | ++ #| | ++ #| | ++ #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ #// // ++ #// Optional Type Length Value objects (variable) // ++ #// // ++ #+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ++ # ++ # 0 1 2 3 4 5 6 7 ++ # +-+-+-+-+-+-+-+-+ ++ # |U|P|O|A|H| U | ++ # +-+-+-+-+-+-+-+-+ ++ ++ name = "IPv6 Segment Routing Extension Header" ++ fields_desc = [ ByteEnumField("nh", 59, ipv6nh), ++ ByteField("len", None), ++ ByteField("type", 4), ++ ByteField("segleft", None), ++ ByteField("lastentry", None), ++ BitField("unused1", 0, 1), ++ BitField("protected", 0, 1), ++ BitField("oam", 0, 1), ++ BitField("alert", 0, 1), ++ BitField("hmac", 0, 1), ++ BitField("unused2", 0, 3), ++ ShortField("tag", 0), ++ IP6ListField("addresses", ["::1"], ++ count_from=lambda pkt: pkt.lastentry+1), ++ PacketListField("tlv_objects", [], IPv6ExtHdrSegmentRoutingTLV, ++ length_from=lambda pkt: 8*pkt.len - 16*(pkt.lastentry+1)) ] ++ ++ overload_fields = { IPv6: { "nh": 43 } } ++ ++ def post_build(self, pkt, pay): ++ ++ if self.len is None: ++ ++ # The extension must be align on 8 bytes ++ tmp_mod = (len(pkt) - 8) % 8 ++ if tmp_mod == 1: ++ warning("IPv6ExtHdrSegmentRouting(): can't pad 1 byte !") ++ elif tmp_mod >= 2: ++ #Add the padding extension ++ tmp_pad = b"\x00" * (tmp_mod-2) ++ tlv = IPv6ExtHdrSegmentRoutingTLVPadding(padding=tmp_pad) ++ pkt += str(tlv) ++ ++ tmp_len = (len(pkt) - 8) / 8 ++ pkt = pkt[:1] + struct.pack("B", tmp_len)+ pkt[2:] ++ ++ if self.segleft is None: ++ tmp_len = len(self.addresses) ++ if tmp_len: ++ tmp_len -= 1 ++ pkt = pkt[:3] + struct.pack("B", tmp_len) + pkt[4:] ++ ++ if self.lastentry is None: ++ #km - changed to contain n-1 ++ tmp_len = len(self.addresses) ++ if tmp_len: ++ tmp_len -= 1 ++ #pkt = pkt[:4] + struct.pack("B", len(self.addresses)) + pkt[5:] ++ pkt = pkt[:4] + struct.pack("B", tmp_len) + pkt[5:] ++ ++ return _IPv6ExtHdr.post_build(self, pkt, pay) ++ ++ + ########################### Fragmentation Header ############################ + + class IPv6ExtHdrFragment(_IPv6ExtHdr): -- cgit 1.2.3-korg