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
22 changes: 14 additions & 8 deletions scapy/contrib/nsh.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from scapy.all import bind_layers
from scapy.fields import BitField, ByteField, ByteEnumField, BitEnumField, \
ShortField, X3BytesField, XIntField, XStrFixedLenField, \
ConditionalField, PacketListField, BitFieldLenField
ConditionalField, FieldListField, PacketListField, BitFieldLenField
from scapy.layers.inet import Ether, IP
from scapy.layers.inet6 import IPv6
from scapy.layers.vxlan import VXLAN
Expand All @@ -30,10 +30,15 @@ class NSHTLV(Packet):
ShortField('class_', 0),
BitField('type', 0, 8),
BitField('reserved', 0, 1),
BitField('length', 0, 7),
PacketListField('metadata', None, XIntField, count_from='length')
BitFieldLenField('length', None, 7, count_of='metadata',
adjust=lambda pkt, x: x * 4),
FieldListField('metadata', [], XIntField('', 0),
length_from=lambda pkt: (pkt.length + 3) // 4 * 4)
]

def extract_padding(self, s):
return b'', s


class NSH(Packet):
"""Network Service Header.
Expand All @@ -46,9 +51,9 @@ class NSH(Packet):
BitField('unused1', 0, 1),
BitField('ttl', 63, 6),
BitFieldLenField('length', None, 6,
count_of='vlch',
length_of='vlch',
adjust=lambda pkt, x: 6 if pkt.mdtype == 1
else x + 2),
else x // 4 + 2),
BitField('unused2', 0, 4),
BitEnumField('mdtype', 1, 4, {0: 'Reserved MDType',
1: 'Fixed Length',
Expand All @@ -65,9 +70,10 @@ class NSH(Packet):
ByteField('si', 0xFF),
ConditionalField(XStrFixedLenField("context_header", "", 16),
lambda pkt: pkt.mdtype == 1),
ConditionalField(PacketListField("vlch", None, NSHTLV,
count_from="length"),
lambda pkt: pkt.mdtype == 2)
ConditionalField(PacketListField(
"vlch", None, NSHTLV,
length_from=lambda pkt: (pkt.length - 2) * 4),
lambda pkt: pkt.mdtype == 2)
]

def mysummary(self):
Expand Down
27 changes: 27 additions & 0 deletions test/contrib/nsh.uts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,30 @@ raw(NSH(mdtype=2, spi=0xF0F0F0, si=0xFF)) == b'\x0f\xc2\x02\x03\xf0\xf0\xf0\xff
= Build a NSH over VXLAN packet and verify bindings
raw(Ether(dst='0c:42:a1:5f:fb:e0', src='b8:59:9f:cd:de:3e')/IPv6(src='::1', dst='::2')/UDP(sport=10, dport=8472)/VXLAN(NextProtocol=4, vni=4660)/NSH()/NSH()/Ether(dst='0c:42:a1:5f:fb:e4', src='b8:59:9f:cd:de:33')/IP(src='10.200.100.10', dst='2.2.2.3')/TCP(sport=123, dport=333)) == b'\x0cB\xa1_\xfb\xe0\xb8Y\x9f\xcd\xde>\x86\xdd`\x00\x00\x00\x00v\x11@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\n!\x18\x00v\x05F\x0c\x00\x00\x04\x00\x124\x00\x0f\xc6\x01\x04\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\xc6\x01\x03\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0cB\xa1_\xfb\xe4\xb8Y\x9f\xcd\xde3\x08\x00E\x00\x00(\x00\x01\x00\x00@\x06\x07\xf9\n\xc8d\n\x02\x02\x02\x03\x00{\x01M\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00\x1bD\x00\x00'


+ MD-Type 2 variable length context headers

= Dissect a NSH MD-Type 2 packet carrying one context header
p = NSH(hex_bytes('0fc40203000001ff00010204deadbeef'))
assert p.mdtype == 2
assert p.length == 4
assert len(p.vlch) == 1
assert p.vlch[0].class_ == 1
assert p.vlch[0].type == 2
assert p.vlch[0].length == 4
assert p.vlch[0].metadata == [0xdeadbeef]
assert raw(p) == hex_bytes('0fc40203000001ff00010204deadbeef')

= Dissect a NSH MD-Type 2 packet carrying two context headers
p = NSH(hex_bytes('0fc60203000001ff00010204deadbeef00020104cafebabe'))
assert p.length == 6
assert len(p.vlch) == 2
assert p.vlch[0].metadata == [0xdeadbeef]
assert p.vlch[1].class_ == 2
assert p.vlch[1].metadata == [0xcafebabe]
assert raw(p) == hex_bytes('0fc60203000001ff00010204deadbeef00020104cafebabe')

= Build a NSH MD-Type 2 packet and check the computed length
p = NSH(mdtype=2, nextproto=3, spi=1, si=255, vlch=[NSHTLV(class_=1, type=2, metadata=[0xdeadbeef])])
assert raw(p) == hex_bytes('0fc40203000001ff00010204deadbeef')
assert NSH(raw(p)).length == 4
Loading