diff --git a/scapy/contrib/isis.py b/scapy/contrib/isis.py index 8f951e14c94a6f9eba0fef5921bb0c4a1af241d7..814439a4f1c193d97b2be5ca4d109206edd666e2 100644 --- a/scapy/contrib/isis.py +++ b/scapy/contrib/isis.py @@ -5,8 +5,9 @@ IS-IS Scapy Extension ~~~~~~~~~~~~~~~~~~~~~ - :copyright: 2014, 2015 BENOCS GmbH, Berlin (Germany) + :copyright: 2014-2016 BENOCS GmbH, Berlin (Germany) :author: Marcel Patzlaff, mpatzlaff@benocs.com + Michal Kaliszan, mkaliszan@benocs.com :license: GPLv2 This module is free software; you can redistribute it and/or @@ -52,10 +53,13 @@ from scapy.config import conf from scapy.fields import * from scapy.packet import * from scapy.layers.clns import network_layer_protocol_ids, register_cln_protocol -from scapy.layers.inet6 import IP6ListField +from scapy.layers.inet6 import IP6ListField, IP6Field +from scapy.utils import fletcher16_checkbytes +from scapy.volatile import RandString, RandByte +import random -EXT_VERSION = "v0.0.1" +EXT_VERSION = "v0.0.2" conf.debug_dissector = True @@ -206,9 +210,128 @@ class ISIS_LspIdField(_ISIS_IdFieldBase): class ISIS_CircuitTypeField(FlagsField): def __init__(self, name="circuittype", default=2, size=8, names=None): - FlagsField.__init__(self, name, default, size, names) if names is None: names = ["L1", "L2", "r0", "r1", "r2", "r3", "r4", "r5"] + FlagsField.__init__(self, name, default, size, names) + + +def _ISIS_GuessTlvClass_Helper(tlv_classes, defaultname, p, **kargs): + cls = conf.raw_layer + if len(p) >= 2: + tlvtype = struct.unpack("!B", p[0])[0] + clsname = tlv_classes.get(tlvtype, defaultname) + cls = globals()[clsname] + + return cls(p, **kargs) + + +class _ISIS_GenericTlv_Base(Packet): + fields_desc = [ByteField("type", 0), + FieldLenField("len", None, length_of="val", fmt="B"), + BoundStrLenField("val", "", length_from=lambda pkt: pkt.len)] + + def guess_payload_class(self, p): + return conf.padding_layer + + +class ISIS_GenericTlv(_ISIS_GenericTlv_Base): + name = "ISIS Generic TLV" + + +class ISIS_GenericSubTlv(_ISIS_GenericTlv_Base): + name = "ISIS Generic Sub-TLV" + + +####################################################################### +## ISIS Sub-TLVs for TLVs 22, 23, 141, 222, 223 ## +####################################################################### +_isis_subtlv_classes_1 = { + 4: "ISIS_LinkLocalRemoteIdentifiersSubTlv", + 6: "ISIS_IPv4InterfaceAddressSubTlv", + 8: "ISIS_IPv4NeighborAddressSubTlv", + 12: "ISIS_IPv6InterfaceAddressSubTlv", + 13: "ISIS_IPv6NeighborAddressSubTlv" +} + +_isis_subtlv_names_1 = { + 4: "Link Local/Remote Identifiers", + 6: "IPv4 Interface Address", + 8: "IPv4 Neighbor Address", + 12: "IPv6 Interface Address", + 13: "IPv6 Neighbor Address" +} + + +def _ISIS_GuessSubTlvClass_1(p, **kargs): + return _ISIS_GuessTlvClass_Helper(_isis_subtlv_classes_1, "ISIS_GenericSubTlv", p, **kargs) + + +class ISIS_IPv4InterfaceAddressSubTlv(ISIS_GenericSubTlv): + name = "ISIS IPv4 Interface Address (S)" + fields_desc = [ByteEnumField("type", 6, _isis_subtlv_names_1), + FieldLenField("len", None, length_of= "address", fmt="B"), + IPField("address", "0.0.0.0")] + + +class ISIS_IPv4NeighborAddressSubTlv(ISIS_GenericSubTlv): + name = "ISIS IPv4 Neighbor Address (S)" + fields_desc = [ByteEnumField("type", 8, _isis_subtlv_names_1), + FieldLenField("len", None, length_of= "address", fmt="B"), + IPField("address", "0.0.0.0")] + + +class ISIS_LinkLocalRemoteIdentifiersSubTlv(ISIS_GenericSubTlv): + name = "ISIS Link Local/Remote Identifiers (S)" + fields_desc = [ByteEnumField("type", 4, _isis_subtlv_names_1), + FieldLenField("len", 8, fmt="B"), + IntField("localid", "0"), + IntField("remoteid", "0")] + + +class ISIS_IPv6InterfaceAddressSubTlv(ISIS_GenericSubTlv): + name = "ISIS IPv6 Interface Address (S)" + fields_desc = [ByteEnumField("type", 12, _isis_subtlv_names_1), + FieldLenField("len", None, length_of= "address", fmt="B"), + IP6Field("address", "::")] + + +class ISIS_IPv6NeighborAddressSubTlv(ISIS_GenericSubTlv): + name = "ISIS IPv6 Neighbor Address (S)" + fields_desc = [ByteEnumField("type", 13, _isis_subtlv_names_1), + FieldLenField("len", None, length_of= "address", fmt="B"), + IP6Field("address", "::")] + + +####################################################################### +## ISIS Sub-TLVs for TLVs 135, 235, 236, and 237 ## +####################################################################### +_isis_subtlv_classes_2 = { + 1: "ISIS_32bitAdministrativeTagSubTlv", + 2: "ISIS_64bitAdministrativeTagSubTlv" +} + +_isis_subtlv_names_2 = { + 1: "32-bit Administrative Tag", + 2: "64-bit Administrative Tag" +} + + +def _ISIS_GuessSubTlvClass_2(p, **kargs): + return _ISIS_GuessTlvClass_Helper(_isis_subtlv_classes_2, "ISIS_GenericSubTlv", p, **kargs) + + +class ISIS_32bitAdministrativeTagSubTlv(ISIS_GenericSubTlv): + name = "ISIS 32-bit Administrative Tag (S)" + fields_desc = [ByteEnumField("type", 1, _isis_subtlv_names_2), + FieldLenField("len", None, length_of= "tags", fmt="B"), + FieldListField("tags", [], IntField("", 0), count_from= lambda pkt: pkt.len / 4)] + + +class ISIS_64bitAdministrativeTagSubTlv(ISIS_GenericSubTlv): + name = "ISIS 64-bit Administrative Tag (S)" + fields_desc = [ByteEnumField("type", 2, _isis_subtlv_names_2), + FieldLenField("len", None, length_of= "tags", fmt="B"), + FieldListField("tags", [], LongField("", 0), count_from= lambda pkt: pkt.len / 8)] ####################################################################### @@ -283,23 +406,7 @@ _isis_tlv_names = { def _ISIS_GuessTlvClass(p, **kargs): - cls = conf.raw_layer - if len(p) >= 2: - tlvtype = struct.unpack("!B", p[0])[0] - clsname = _isis_tlv_classes.get(tlvtype, "ISIS_GenericTlv") - cls = globals()[clsname] - - return cls(p, **kargs) - - -class ISIS_GenericTlv(Packet): - name = "ISIS Generic TLV" - fields_desc = [ByteEnumField("type", 0, _isis_tlv_names), - FieldLenField("len", None, length_of="val", fmt="B"), - BoundStrLenField("val", "", length_from=lambda pkt: pkt.len)] - - def guess_payload_class(self, p): - return conf.padding_layer + return _ISIS_GuessTlvClass_Helper(_isis_tlv_classes, "ISIS_GenericTlv", p, **kargs) class ISIS_AreaEntry(Packet): @@ -347,20 +454,6 @@ class ISIS_DynamicHostnameTlv(ISIS_GenericTlv): BoundStrLenField("hostname", "", length_from=lambda pkt: pkt.len)] -class ISIS_GenericSubTlv(Packet): - name = "ISIS Generic Sub-TLV" - fields_desc = [ByteField("type", 0), - FieldLenField("len", None, length_of="val", fmt="B"), - BoundStrLenField("val", "", length_from=lambda pkt: pkt.len)] - - def guess_payload_class(self, p): - return conf.padding_layer - - -def _isis_guess_subtlv_cls(p, **kargs): - return ISIS_GenericSubTlv(p, **kargs) - - class ISIS_ExtendedIpPrefix(Packet): name = "ISIS Extended IP Prefix" fields_desc = [ @@ -369,8 +462,8 @@ class ISIS_ExtendedIpPrefix(Packet): BitField("subtlvindicator", 0, 1), BitFieldLenField("pfxlen", None, 6, length_of="pfx"), IPPrefixField("pfx", None, wordbytes=1, length_from=lambda x: x.pfxlen), - ConditionalField(FieldLenField("subtlvslen", None, length_of=lambda x: x.subtlvs, fmt= "B"), lambda pkt: pkt.subtlvindicator == 1), - ConditionalField(PacketListField("subtlvs", [], _isis_guess_subtlv_cls, length_from=lambda x: x.subtlvslen), lambda pkt: pkt.subtlvindicator == 1) + ConditionalField(FieldLenField("subtlvslen", None, length_of="subtlvs", fmt= "B"), lambda pkt: pkt.subtlvindicator == 1), + ConditionalField(PacketListField("subtlvs", [], _ISIS_GuessSubTlvClass_2, length_from=lambda x: x.subtlvslen), lambda pkt: pkt.subtlvindicator == 1) ] def extract_padding(self, s): @@ -386,15 +479,17 @@ class ISIS_ExtendedIpReachabilityTlv(ISIS_GenericTlv): class ISIS_ExtendedIsNeighbourEntry(Packet): name = "ISIS Extended IS Neighbour Entry" - fields_desc = [ISIS_NodeIdField("neighbourid", "0102.0304.0506.07"), - ThreeBytesField("metric", 1), - FieldLenField("subtlvslen", None, length_of="subtlvs", fmt= "B"), - ConditionalField(PacketListField("subtlvs", [], _isis_guess_subtlv_cls, length_from=lambda x: x.subtlvslen), lambda pkt: pkt.subtlvslen > 0)] + fields_desc = [ + ISIS_NodeIdField("neighbourid", "0102.0304.0506.07"), + ThreeBytesField("metric", 1), + FieldLenField("subtlvslen", None, length_of="subtlvs", fmt= "B"), + PacketListField("subtlvs", [], _ISIS_GuessSubTlvClass_1, length_from=lambda x: x.subtlvslen) + ] def extract_padding(self, s): return "", s - + class ISIS_ExtendedIsReachabilityTlv(ISIS_GenericTlv): name = "ISIS Extended IS Reachability TLV" fields_desc = [ByteEnumField("type", 22, _isis_tlv_names), @@ -428,8 +523,8 @@ class ISIS_Ipv6Prefix(Packet): BitField("reserved", 0, 5), FieldLenField("pfxlen", None, length_of="pfx", fmt="B"), IP6PrefixField("pfx", None, wordbytes=1, length_from=lambda x: x.pfxlen), - ConditionalField(FieldLenField("subtlvslen", None, length_of=lambda x: x.subtlvs, fmt= "B"), lambda pkt: pkt.subtlvindicator == 1), - ConditionalField(PacketListField("subtlvs", [], _isis_guess_subtlv_cls, length_from=lambda x: x.subtlvslen), lambda pkt: pkt.subtlvindicator == 1) + ConditionalField(FieldLenField("subtlvslen", None, length_of="subtlvs", fmt= "B"), lambda pkt: pkt.subtlvindicator == 1), + ConditionalField(PacketListField("subtlvs", [], _ISIS_GuessSubTlvClass_2, length_from=lambda x: x.subtlvslen), lambda pkt: pkt.subtlvindicator == 1) ] def extract_padding(self, s): @@ -767,3 +862,4 @@ bind_layers(ISIS_CommonHdr, ISIS_L1_CSNP, hdrlen=33, pdutype=24) bind_layers(ISIS_CommonHdr, ISIS_L2_CSNP, hdrlen=33, pdutype=25) bind_layers(ISIS_CommonHdr, ISIS_L1_PSNP, hdrlen=17, pdutype=26) bind_layers(ISIS_CommonHdr, ISIS_L2_PSNP, hdrlen=17, pdutype=27) + diff --git a/scapy/contrib/isis.uts b/scapy/contrib/isis.uts index 78cc12e7c02134ef8412a5997e597f1d2a01eebe..95c9ba2025372d372d900d4fe2d75abc9dceb496 100644 --- a/scapy/contrib/isis.uts +++ b/scapy/contrib/isis.uts @@ -1,6 +1,11 @@ % IS-IS Tests * Tests for the IS-IS layer ++ Syntax check + += Import the isis layer +from scapy.contrib.isis import * + + Basic Layer Tests = Layer Binding @@ -13,9 +18,20 @@ assert(p[ISIS_CommonHdr].pdutype == 17) assert(p[ISIS_CommonHdr].hdrlen == 20) + Package Tests + += P2P Hello +p = Dot3(dst="09:00:2b:00:00:05",src="00:00:00:aa:00:8c")/LLC()/ISIS_CommonHdr()/ISIS_P2P_Hello( + holdingtime=40, sourceid="1720.1600.8016", + tlvs=[ + ISIS_ProtocolsSupportedTlv(nlpids=["IPv4", "IPv6"]) + ]) +p = p.__class__(str(p)) +assert(p[ISIS_P2P_Hello].pdulength == 24) +assert(network_layer_protocol_ids[p[ISIS_ProtocolsSupportedTlv].nlpids[1]] == "IPv6") + = LSP p = Dot3(dst="09:00:2b:00:00:05",src="00:00:00:aa:00:8c")/LLC()/ISIS_CommonHdr()/ISIS_L2_LSP( - lifetime=863, lspid="1720.1600.8016.00-00", seqnum=0x1f0, typeblock="L1+L2", + lifetime=863, lspid="1720.1600.8016.00-00", seqnum=0x1f0, typeblock="L1+L2", tlvs=[ ISIS_AreaTlv( areas=[ISIS_AreaEntry(areaid="49.1000")] @@ -50,8 +66,71 @@ p = Dot3(dst="09:00:2b:00:00:05",src="00:00:00:aa:00:8c")/LLC()/ISIS_CommonHdr() ISIS_ExtendedIsReachabilityTlv( neighbours=[ISIS_ExtendedIsNeighbourEntry(neighbourid="1720.1600.8004.00", metric=10)] ) - ] - ) + ]) p = p.__class__(str(p)) assert(p[ISIS_L2_LSP].pdulength == 150) -assert(p[ISIS_L2_LSP].checksum == 0x8701) \ No newline at end of file +assert(p[ISIS_L2_LSP].checksum == 0x8701) + += LSP with Sub-TLVs +p = Dot3(dst="09:00:2b:00:00:05",src="00:00:00:aa:00:8c")/LLC()/ISIS_CommonHdr()/ISIS_L2_LSP( + lifetime=863, lspid="1720.1600.8016.00-00", seqnum=0x1f0, typeblock="L1+L2", + tlvs=[ + ISIS_AreaTlv( + areas=[ISIS_AreaEntry(areaid="49.1000")] + ), + ISIS_ProtocolsSupportedTlv( + nlpids=["IPv4", "IPv6"] + ), + ISIS_DynamicHostnameTlv( + hostname="BR-HH" + ), + ISIS_IpInterfaceAddressTlv( + addresses=["172.16.8.16"] + ), + ISIS_GenericTlv( + type=134, + val="\xac\x10\x08\x10" + ), + ISIS_ExtendedIpReachabilityTlv( + pfxs=[ + ISIS_ExtendedIpPrefix(metric=0, pfx="172.16.8.16/32"), + ISIS_ExtendedIpPrefix(metric=10, pfx="10.1.0.109/30", subtlvindicator=1, + subtlvs=[ + ISIS_32bitAdministrativeTagSubTlv(tags=[321, 123]), + ISIS_64bitAdministrativeTagSubTlv(tags=[54321, 4294967311]) + ]), + ISIS_ExtendedIpPrefix(metric=10, pfx="10.1.0.181/30", subtlvindicator=1, + subtlvs=[ + ISIS_GenericSubTlv(type=123, val="\x11\x1f\x01\x1c") + ]) + ] + ), + ISIS_Ipv6ReachabilityTlv( + pfxs=[ + ISIS_Ipv6Prefix(metric=0, pfx="fe10:1::10/128"), + ISIS_Ipv6Prefix(metric=10, pfx="fd1f:1::/64", subtlvindicator=1, + subtlvs=[ + ISIS_GenericSubTlv(type=99, val="\x1f\x01\x1f\x01\x11\x1f\x01\x1c") + ]), + ISIS_Ipv6Prefix(metric=10, pfx="fd1f:1:12::/64") + ] + ), + ISIS_ExtendedIsReachabilityTlv( + neighbours=[ + ISIS_ExtendedIsNeighbourEntry(neighbourid="1720.1600.8004.00", metric=10, + subtlvs=[ + ISIS_IPv4InterfaceAddressSubTlv(address="172.16.8.4"), + ISIS_LinkLocalRemoteIdentifiersSubTlv(localid=418, remoteid=54321), + ISIS_IPv6NeighborAddressSubTlv(address="fe10:1::5") + ]) + ] + ) + ]) +p = p.__class__(str(p)) +assert(p[ISIS_L2_LSP].pdulength == 231) +assert(p[ISIS_L2_LSP].checksum == 0xf8df) +assert(p[ISIS_ExtendedIpReachabilityTlv].pfxs[1].subtlvs[1].tags[0]==54321) +assert(p[ISIS_Ipv6ReachabilityTlv].pfxs[1].subtlvs[0].len==8) +assert(p[ISIS_ExtendedIsReachabilityTlv].neighbours[0].subtlvs[0].address=='172.16.8.4') +assert(p[ISIS_ExtendedIsReachabilityTlv].neighbours[0].subtlvs[1].localid==418) + diff --git a/scapy/contrib/ospf.py b/scapy/contrib/ospf.py index 7b10cea6f1d8b6104253e93ddce10567601c255f..83acc19da584a1de2736ccf5b1d72c8f8c8c085e 100644 --- a/scapy/contrib/ospf.py +++ b/scapy/contrib/ospf.py @@ -36,9 +36,9 @@ class OSPFOptionsField(FlagsField): def __init__(self, name="options", default=0, size=8, names=None): - FlagsField.__init__(self, name, default, size, names) if names is None: names = ["MT", "E", "MC", "NP", "L", "DC", "O", "DN"] + FlagsField.__init__(self, name, default, size, names) _OSPF_types = {1: "Hello", @@ -133,9 +133,9 @@ class LLS_ExtendedOptionsField(FlagsField): def __init__(self, name="options", default=0, size=32, names=None): - FlagsField.__init__(self, name, default, size, names) if names is None: names = ["LR", "RS"] + FlagsField.__init__(self, name, default, size, names) class LLS_Extended_Options(LLS_Generic_TLV): @@ -460,9 +460,9 @@ class OSPFv3OptionsField(FlagsField): def __init__(self, name="options", default=0, size=24, names=None): - FlagsField.__init__(self, name, default, size, names) if names is None: names = ["V6", "E", "MC", "N", "R", "DC", "AF", "L", "I", "F"] + FlagsField.__init__(self, name, default, size, names) class OSPFv3_Hello(Packet): @@ -577,9 +577,9 @@ class OSPFv3PrefixOptionsField(FlagsField): def __init__(self, name="prefixoptions", default=0, size=8, names=None): - FlagsField.__init__(self, name, default, size, names) if names is None: names = ["NU", "LA", "MC", "P"] + FlagsField.__init__(self, name, default, size, names) class OSPFv3_Inter_Area_Prefix_LSA(OSPF_BaseLSA):