86890704fd
todo: add documentation & wireshark dissector
285 lines
11 KiB
Text
Executable file
285 lines
11 KiB
Text
Executable file
from enum import test
|
|
% LLDP test campaign
|
|
|
|
#
|
|
# execute test:
|
|
# > test/run_tests -P "load_contrib('lldp')" -t scapy/contrib/lldp.uts
|
|
#
|
|
|
|
+ Basic layer handling
|
|
= build basic LLDP frames
|
|
|
|
frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/ \
|
|
LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\x06\x05\x04\x03\x02\x01') / \
|
|
LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\x01\x02\x03\x04\x05\x06')/\
|
|
LLDPDUTimeToLive()/\
|
|
LLDPDUSystemName(system_name='mate')/\
|
|
LLDPDUSystemCapabilities(telephone_available=1, router_available=1, telephone_enabled=1)/\
|
|
LLDPDUManagementAddress(
|
|
management_address_subtype=LLDPDUManagementAddress.SUBTYPE_MANAGEMENT_ADDRESS_IPV4,
|
|
management_address='1.2.3.4',
|
|
interface_numbering_subtype=LLDPDUManagementAddress.SUBTYPE_INTERFACE_NUMBER_IF_INDEX,
|
|
interface_number=23,
|
|
object_id='abcd') / \
|
|
LLDPDUEndOfLLDPDU()
|
|
|
|
frm = frm.build()
|
|
frm = Ether(frm)
|
|
|
|
= add padding if required
|
|
|
|
conf.contribs['LLDP'].strict_mode_disable()
|
|
frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC) / \
|
|
LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_INTERFACE_NAME, id='eth0') / \
|
|
LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id='06:05:04:03:02:01') / \
|
|
LLDPDUTimeToLive() / \
|
|
LLDPDUEndOfLLDPDU()
|
|
assert(len(raw(frm)) == 60)
|
|
assert(len(raw(Ether(raw(frm))[Padding])) == 24)
|
|
|
|
frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC) / \
|
|
LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_INTERFACE_NAME, id='eth012345678901234567890123') / \
|
|
LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id='06:05:04:03:02:01') / \
|
|
LLDPDUTimeToLive() / \
|
|
LLDPDUEndOfLLDPDU()
|
|
assert (len(raw(frm)) == 60)
|
|
assert (len(raw(Ether(raw(frm))[Padding])) == 1)
|
|
|
|
frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC) / \
|
|
LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_INTERFACE_NAME, id='eth0123456789012345678901234') / \
|
|
LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id='06:05:04:03:02:01') / \
|
|
LLDPDUTimeToLive() / \
|
|
LLDPDUEndOfLLDPDU()
|
|
assert (len(raw(frm)) == 60)
|
|
try:
|
|
Ether(raw(frm))[Padding]
|
|
assert False
|
|
except IndexError:
|
|
pass
|
|
|
|
|
|
= Advanced test: check definitions and length of complex IDs
|
|
|
|
pkt = Ether()/LLDPDUChassisID(id="ff:dd:ee:bb:aa:99", subtype=0x04)/LLDPDUPortID(subtype=0x03, id="aa:bb:cc:dd:ee:ff")/LLDPDUTimeToLive(ttl=120)/LLDPDUEndOfLLDPDU()
|
|
pkt = Ether(raw(pkt))
|
|
assert pkt[LLDPDUChassisID].fields_desc[2].i2s == LLDPDUChassisID.LLDP_CHASSIS_ID_TLV_SUBTYPES
|
|
assert pkt[LLDPDUChassisID].fields_desc[3].subtypes_dict == LLDPDUChassisID.LLDP_CHASSIS_ID_TLV_SUBTYPES_FIELDS
|
|
assert pkt[LLDPDUPortID].fields_desc[2].i2s == LLDPDUPortID.LLDP_PORT_ID_TLV_SUBTYPES
|
|
assert pkt[LLDPDUPortID].fields_desc[3].subtypes_dict == LLDPDUPortID.LLDP_PORT_ID_TLV_SUBTYPES_FIELDS
|
|
assert pkt[LLDPDUChassisID]._length == 7
|
|
assert pkt[LLDPDUPortID]._length == 7
|
|
|
|
+ strict mode handling - build
|
|
= basic frame structure
|
|
|
|
conf.contribs['LLDP'].strict_mode_enable()
|
|
|
|
# invalid length in LLDPDUEndOfLLDPDU
|
|
try:
|
|
frm = Ether()/LLDPDUChassisID(id='slartibart')/LLDPDUPortID(id='42')/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU(_length=8)
|
|
frm.build()
|
|
assert False
|
|
except LLDPInvalidLengthField:
|
|
pass
|
|
|
|
# missing chassis id
|
|
try:
|
|
frm = Ether()/LLDPDUChassisID()/LLDPDUPortID(id='42')/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()
|
|
frm.build()
|
|
assert False
|
|
except LLDPInvalidLengthField:
|
|
pass
|
|
|
|
# missing management address
|
|
try:
|
|
frm = Ether()/LLDPDUChassisID(id='slartibart')/LLDPDUPortID(id='42')/LLDPDUTimeToLive()/LLDPDUManagementAddress()/LLDPDUEndOfLLDPDU()
|
|
frm.build()
|
|
assert False
|
|
except LLDPInvalidLengthField:
|
|
pass
|
|
|
|
+ strict mode handling - dissect
|
|
= basic frame structure
|
|
|
|
conf.contribs['LLDP'].strict_mode_enable()
|
|
# missing PortIDTLV
|
|
try:
|
|
frm = Ether() / LLDPDUChassisID(id='slartibart') / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU()
|
|
Ether(frm.build())
|
|
assert False
|
|
except LLDPInvalidFrameStructure:
|
|
pass
|
|
|
|
# invalid order
|
|
try:
|
|
frm = Ether() / LLDPDUPortID(id='42') / LLDPDUChassisID(id='slartibart') / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU()
|
|
Ether(frm.build())
|
|
assert False
|
|
except LLDPInvalidFrameStructure:
|
|
pass
|
|
|
|
# layer LLDPDUPortID occurs twice
|
|
try:
|
|
frm = Ether() / LLDPDUChassisID(id='slartibart') / LLDPDUPortID(id='42') / LLDPDUPortID(id='23') / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU()
|
|
Ether(frm.build())
|
|
assert False
|
|
except LLDPInvalidFrameStructure:
|
|
pass
|
|
|
|
# missing LLDPDUEndOfLLDPDU
|
|
try:
|
|
frm = Ether() / LLDPDUChassisID(id='slartibart') / LLDPDUPortID(id='42') / \
|
|
LLDPDUPortID(id='23') / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU()
|
|
Ether(frm.build())
|
|
assert False
|
|
except LLDPInvalidFrameStructure:
|
|
pass
|
|
|
|
conf.contribs['LLDP'].strict_mode_disable()
|
|
frm = Ether()/LLDPDUChassisID()/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU()
|
|
frm = Ether(frm.build())
|
|
|
|
= length fields / value sizes checks
|
|
|
|
conf.contribs['LLDP'].strict_mode_enable()
|
|
# missing chassis id => invalid length
|
|
try:
|
|
frm = Ether() / LLDPDUChassisID() / LLDPDUPortID(id='42') / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU()
|
|
Ether(frm.build())
|
|
assert False
|
|
except LLDPInvalidLengthField:
|
|
pass
|
|
|
|
# invalid length in LLDPDUEndOfLLDPDU
|
|
try:
|
|
frm = Ether()/LLDPDUChassisID(id='slartibart')/LLDPDUPortID(id='42')/LLDPDUTimeToLive()/LLDPDUEndOfLLDPDU(_length=8)
|
|
Ether(frm.build())
|
|
assert False
|
|
except LLDPInvalidLengthField:
|
|
pass
|
|
|
|
# invalid management address
|
|
try:
|
|
frm = Ether() / LLDPDUChassisID(id='slartibart') / LLDPDUPortID(id='42') / LLDPDUTimeToLive() / LLDPDUManagementAddress() / LLDPDUEndOfLLDPDU()
|
|
Ether(frm.build())
|
|
assert False
|
|
except LLDPInvalidLengthField:
|
|
pass
|
|
|
|
conf.contribs['LLDP'].strict_mode_disable()
|
|
|
|
frm = Ether() / LLDPDUChassisID(id='slartibart') / LLDPDUPortID(id='42') / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU()
|
|
frm = Ether(frm.build())
|
|
|
|
frm = Ether() / LLDPDUChassisID() / LLDPDUPortID() / LLDPDUTimeToLive() / LLDPDUEndOfLLDPDU(_length=8)
|
|
frm = Ether(frm.build())
|
|
|
|
= test attribute values
|
|
|
|
conf.contribs['LLDP'].strict_mode_enable()
|
|
|
|
frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/ \
|
|
LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id='06:05:04:03:02:01') / \
|
|
LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id='01:02:03:04:05:06')/\
|
|
LLDPDUTimeToLive()/\
|
|
LLDPDUSystemName(system_name='things will')/\
|
|
LLDPDUSystemCapabilities(telephone_available=1,
|
|
router_available=1,
|
|
telephone_enabled=1,
|
|
router_enabled=1)/\
|
|
LLDPDUManagementAddress(
|
|
management_address_subtype=LLDPDUManagementAddress.SUBTYPE_MANAGEMENT_ADDRESS_IPV4,
|
|
management_address='1.2.3.4',
|
|
interface_numbering_subtype=LLDPDUManagementAddress.SUBTYPE_INTERFACE_NUMBER_IF_INDEX,
|
|
interface_number=23,
|
|
object_id='burn') / \
|
|
LLDPDUSystemDescription(description='without tests.') / \
|
|
LLDPDUPortDescription(description='always!') / \
|
|
LLDPDUEndOfLLDPDU()
|
|
|
|
frm = Ether(frm.build())
|
|
|
|
assert frm[LLDPDUChassisID].id == '06:05:04:03:02:01'
|
|
assert frm[LLDPDUPortID].id == '01:02:03:04:05:06'
|
|
sys_capabilities = frm[LLDPDUSystemCapabilities]
|
|
assert sys_capabilities.reserved_5_available == 0
|
|
assert sys_capabilities.reserved_4_available == 0
|
|
assert sys_capabilities.reserved_3_available == 0
|
|
assert sys_capabilities.reserved_2_available == 0
|
|
assert sys_capabilities.reserved_1_available == 0
|
|
assert sys_capabilities.two_port_mac_relay_available == 0
|
|
assert sys_capabilities.s_vlan_component_available == 0
|
|
assert sys_capabilities.c_vlan_component_available == 0
|
|
assert sys_capabilities.station_only_available == 0
|
|
assert sys_capabilities.docsis_cable_device_available == 0
|
|
assert sys_capabilities.telephone_available == 1
|
|
assert sys_capabilities.router_available == 1
|
|
assert sys_capabilities.wlan_access_point_available == 0
|
|
assert sys_capabilities.mac_bridge_available == 0
|
|
assert sys_capabilities.repeater_available == 0
|
|
assert sys_capabilities.other_available == 0
|
|
assert sys_capabilities.reserved_5_enabled == 0
|
|
assert sys_capabilities.reserved_4_enabled == 0
|
|
assert sys_capabilities.reserved_3_enabled == 0
|
|
assert sys_capabilities.reserved_2_enabled == 0
|
|
assert sys_capabilities.reserved_1_enabled == 0
|
|
assert sys_capabilities.two_port_mac_relay_enabled == 0
|
|
assert sys_capabilities.s_vlan_component_enabled == 0
|
|
assert sys_capabilities.c_vlan_component_enabled == 0
|
|
assert sys_capabilities.station_only_enabled == 0
|
|
assert sys_capabilities.docsis_cable_device_enabled == 0
|
|
assert sys_capabilities.telephone_enabled == 1
|
|
assert sys_capabilities.router_enabled == 1
|
|
assert sys_capabilities.wlan_access_point_enabled == 0
|
|
assert sys_capabilities.mac_bridge_enabled == 0
|
|
assert sys_capabilities.repeater_enabled == 0
|
|
assert sys_capabilities.other_enabled == 0
|
|
assert frm[LLDPDUManagementAddress].management_address == b'1.2.3.4'
|
|
assert frm[LLDPDUSystemName].system_name == b'things will'
|
|
assert frm[LLDPDUManagementAddress].object_id == b'burn'
|
|
assert frm[LLDPDUSystemDescription].description == b'without tests.'
|
|
assert frm[LLDPDUPortDescription].description == b'always!'
|
|
|
|
+ organisation specific layers
|
|
|
|
= ThreeBytesEnumField tests
|
|
|
|
three_b_enum_field = ThreeBytesEnumField('test', 0x00,
|
|
{
|
|
0x0e: 'fourteen',
|
|
0x00: 'zero',
|
|
0x5566: 'five-six',
|
|
0x0e0000: 'fourteen-zero-zero',
|
|
0x0e0100: 'fourteen-one-zero',
|
|
0x112233: '1#2#3'
|
|
})
|
|
|
|
assert(three_b_enum_field.i2repr(None, 0) == 'zero')
|
|
assert(three_b_enum_field.i2repr(None, 0x0e) == 'fourteen')
|
|
assert(three_b_enum_field.i2repr(None, 0x5566) == 'five-six')
|
|
assert(three_b_enum_field.i2repr(None, 0x112233) == '1#2#3')
|
|
assert(three_b_enum_field.i2repr(None, 0x0e0000) == 'fourteen-zero-zero')
|
|
assert(three_b_enum_field.i2repr(None, 0x0e0100) == 'fourteen-one-zero')
|
|
assert(three_b_enum_field.i2repr(None, 0x01) == '1')
|
|
assert(three_b_enum_field.i2repr(None, 0x49763) == '300899')
|
|
|
|
= LLDPDUGenericOrganisationSpecific tests
|
|
|
|
frm = Ether(src='01:01:01:01:01:01', dst=LLDP_NEAREST_BRIDGE_MAC)/\
|
|
LLDPDUChassisID(subtype=LLDPDUChassisID.SUBTYPE_MAC_ADDRESS, id=b'\x06\x05\x04\x03\x02\x01')/\
|
|
LLDPDUPortID(subtype=LLDPDUPortID.SUBTYPE_MAC_ADDRESS, id=b'\x01\x02\x03\x04\x05\x06')/\
|
|
LLDPDUTimeToLive()/\
|
|
LLDPDUGenericOrganisationSpecific(org_code=LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO,
|
|
subtype=0x42,
|
|
data=b'FooBar'*5
|
|
)/\
|
|
LLDPDUEndOfLLDPDU()
|
|
|
|
frm = frm.build()
|
|
frm = Ether(frm)
|
|
org_spec_layer = frm[LLDPDUGenericOrganisationSpecific]
|
|
assert(org_spec_layer)
|
|
assert(org_spec_layer._type == 127)
|
|
assert(org_spec_layer.org_code == LLDPDUGenericOrganisationSpecific.ORG_UNIQUE_CODE_PNO)
|
|
assert(org_spec_layer.subtype == 0x42)
|
|
assert(org_spec_layer._length == 34)
|