98 lines
3.5 KiB
Python
98 lines
3.5 KiB
Python
# This file is part of Scapy
|
|
# Scapy is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 2 of the License, or
|
|
# any later version.
|
|
#
|
|
# Scapy is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with Scapy. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
# scapy.contrib.description = NSH Protocol
|
|
# scapy.contrib.status = loads
|
|
|
|
from scapy.all import bind_layers
|
|
from scapy.fields import BitField, ByteField, ByteEnumField
|
|
from scapy.fields import ShortField, X3BytesField, XIntField
|
|
from scapy.fields import ConditionalField, PacketListField, BitFieldLenField
|
|
from scapy.layers.inet import Ether, IP
|
|
from scapy.layers.inet6 import IPv6
|
|
from scapy.layers.vxlan import VXLAN
|
|
from scapy.packet import Packet
|
|
from scapy.layers.l2 import GRE
|
|
|
|
from scapy.contrib.mpls import MPLS
|
|
|
|
#
|
|
# NSH Support
|
|
# https://www.ietf.org/id/draft-ietf-sfc-nsh-05.txt
|
|
#
|
|
|
|
|
|
class Metadata(Packet):
|
|
name = 'NSH metadata'
|
|
fields_desc = [XIntField('value', 0)]
|
|
|
|
|
|
class NSHTLV(Packet):
|
|
"NSH MD-type 2 - Variable Length Context Headers"
|
|
name = "NSHTLV"
|
|
fields_desc = [
|
|
ShortField('Class', 0),
|
|
BitField('Critical', 0, 1),
|
|
BitField('Type', 0, 7),
|
|
BitField('Reserved', 0, 3),
|
|
BitField('Len', 0, 5),
|
|
PacketListField('Metadata', None, XIntField, count_from='Len')
|
|
]
|
|
|
|
|
|
class NSH(Packet):
|
|
"""Network Service Header.
|
|
NSH MD-type 1 if there is no ContextHeaders"""
|
|
name = "NSH"
|
|
|
|
fields_desc = [
|
|
BitField('Ver', 0, 2),
|
|
BitField('OAM', 0, 1),
|
|
BitField('Critical', 0, 1),
|
|
BitField('Reserved', 0, 6),
|
|
BitFieldLenField('Len', None, 6,
|
|
count_of='ContextHeaders',
|
|
adjust=lambda pkt, x: 6 if pkt.MDType == 1 else x + 2),
|
|
ByteEnumField('MDType', 1, {1: 'Fixed Length',
|
|
2: 'Variable Length'}),
|
|
ByteEnumField('NextProto', 3, {1: 'IPv4',
|
|
2: 'IPv6',
|
|
3: 'Ethernet',
|
|
4: 'NSH',
|
|
5: 'MPLS'}),
|
|
X3BytesField('NSP', 0),
|
|
ByteField('NSI', 1),
|
|
ConditionalField(XIntField('NPC', 0), lambda pkt: pkt.MDType == 1),
|
|
ConditionalField(XIntField('NSC', 0), lambda pkt: pkt.MDType == 1),
|
|
ConditionalField(XIntField('SPC', 0), lambda pkt: pkt.MDType == 1),
|
|
ConditionalField(XIntField('SSC', 0), lambda pkt: pkt.MDType == 1),
|
|
ConditionalField(PacketListField("ContextHeaders", None,
|
|
NSHTLV, count_from="Length"),
|
|
lambda pkt: pkt.MDType == 2)
|
|
]
|
|
|
|
def mysummary(self):
|
|
return self.sprintf("NSP: %NSP% - NSI: %NSI%")
|
|
|
|
|
|
bind_layers(Ether, NSH, {'type': 0x894F}, type=0x894F)
|
|
bind_layers(VXLAN, NSH, {'flags': 0xC, 'NextProtocol': 4}, NextProtocol=4)
|
|
bind_layers(GRE, NSH, {'proto': 0x894F}, proto=0x894F)
|
|
|
|
bind_layers(NSH, IP, {'NextProto': 1}, NextProto=1)
|
|
bind_layers(NSH, IPv6, {'NextProto': 2}, NextProto=2)
|
|
bind_layers(NSH, Ether, {'NextProto': 3}, NextProto=3)
|
|
bind_layers(NSH, NSH, {'NextProto': 4}, NextProto=4)
|
|
bind_layers(NSH, MPLS, {'NextProto': 5}, NextProto=5)
|