Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 48 additions & 5 deletions scapy/layers/hsrp.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,47 @@
"""

from scapy.config import conf
from scapy.fields import ByteEnumField, ByteField, IPField, SourceIPField, \
StrFixedLenField, XIntField, XShortField
from scapy.compat import orb
from scapy.fields import ByteEnumField, ByteField, IntField, IPField, \
ShortEnumField, ShortField, SourceIPField, StrFixedLenField, \
XIntField, XShortField
from scapy.packet import Packet, bind_layers, bind_bottom_up
from scapy.layers.inet import DestIPField, UDP


_HSRP_OPCODES = {0: "Hello", 1: "Coup", 2: "Resign", 3: "Advertise"}
_HSRP_STATES = {
0: "Initial",
1: "Learn",
2: "Listen",
4: "Speak",
8: "Standby",
16: "Active",
}
_HSRP_ADVERTISE_TYPES = {1: "HSRP interface state"}
_HSRP_ADVERTISE_STATES = {1: "Active", 2: "Passive"}


class HSRP(Packet):
name = "HSRP"
fields_desc = [
ByteField("version", 0),
ByteEnumField("opcode", 0, {0: "Hello", 1: "Coup", 2: "Resign", 3: "Advertise"}), # noqa: E501
ByteEnumField("state", 16, {0: "Initial", 1: "Learn", 2: "Listen", 4: "Speak", 8: "Standby", 16: "Active"}), # noqa: E501
ByteEnumField("opcode", 0, _HSRP_OPCODES),
ByteEnumField("state", 16, _HSRP_STATES),
ByteField("hellotime", 3),
ByteField("holdtime", 10),
ByteField("priority", 120),
ByteField("group", 1),
ByteField("reserved", 0),
StrFixedLenField("auth", b"cisco" + b"\00" * 3, 8),
IPField("virtualIP", "192.168.1.1")]
IPField("virtualIP", "192.168.1.1")
]

@classmethod
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt and len(_pkt) >= 2 and orb(_pkt[1:2]) == 3:
return HSRPAdvertise
return cls

def guess_payload_class(self, payload):
if self.underlayer.len > 28:
Expand All @@ -40,6 +62,27 @@ def guess_payload_class(self, payload):
return Packet.guess_payload_class(self, payload)


class HSRPAdvertise(Packet):
name = "HSRP Advertise"
fields_desc = [
ByteField("version", 0),
ByteEnumField("opcode", 3, _HSRP_OPCODES),
ShortEnumField("type", 1, _HSRP_ADVERTISE_TYPES),
ShortField("length", 10),
ByteEnumField("state", 1, _HSRP_ADVERTISE_STATES),
ByteField("reserved1", 0),
ShortField("activegroups", 0),
ShortField("passivegroups", 0),
IntField("reserved2", 0),
]

@classmethod
def dispatch_hook(cls, _pkt=None, *args, **kargs):
if _pkt and len(_pkt) >= 2 and orb(_pkt[1:2]) != 3:
return HSRP
return cls


class HSRPmd5(Packet):
name = "HSRP MD5 Authentication"
fields_desc = [
Expand Down
21 changes: 20 additions & 1 deletion test/scapy/layers/hsrp.uts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,23 @@ assert pkt[IP].dst == "224.0.0.2" and pkt[UDP].sport == pkt[UDP].dport == 1985
assert pkt[HSRP].opcode == 0 and pkt[HSRP].state == 16
assert pkt[HSRPmd5].type == 4 and pkt[HSRPmd5].sourceip == defaddr


= HSRP - Advertise build & dissection
advertise_raw = b"\x00\x03\x00\x01\x00\x0e\x02\x00\x00\x00\x00\x01o\x00\x00\x00"
pkt = HSRP(advertise_raw)
assert isinstance(pkt, HSRPAdvertise)
assert pkt.opcode == 3
assert pkt.type == 1 and pkt.length == 14
assert pkt.state == 2 and pkt.reserved1 == 0
assert pkt.activegroups == 0 and pkt.passivegroups == 1
assert pkt.reserved2 == 0x6f000000
assert raw(
HSRPAdvertise(
type=1,
length=14,
state=2,
reserved1=0,
activegroups=0,
passivegroups=1,
reserved2=0x6f000000,
)
) == advertise_raw