1 # This file is part of Scapy 2 # Scapy is free software: you can redistribute it and/or modify 3 # it under the terms of the GNU General Public License as published by 4 # the Free Software Foundation, either version 2 of the License, or 5 # any later version. 6 # 7 # Scapy is distributed in the hope that it will be useful, 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 # GNU General Public License for more details. 11 # 12 # You should have received a copy of the GNU General Public License 13 # along with Scapy. If not, see <http://www.gnu.org/licenses/>. 14 15 # scapy.contrib.description = NSH Protocol 16 # scapy.contrib.status = loads 17 18 from scapy.all import bind_layers 19 from scapy.fields import BitField, ByteField, ByteEnumField 20 from scapy.fields import ShortField, X3BytesField, XIntField 21 from scapy.fields import ConditionalField, PacketListField, BitFieldLenField 22 from scapy.layers.inet import Ether, IP 23 from scapy.layers.inet6 import IPv6 24 from scapy.layers.vxlan import VXLAN 25 from scapy.packet import Packet 26 from scapy.layers.l2 import GRE 27 28 from scapy.contrib.mpls import MPLS 29 30 # 31 # NSH Support 32 # https://www.ietf.org/id/draft-ietf-sfc-nsh-05.txt 33 # 34 35 36 class Metadata(Packet): 37 name = 'NSH metadata' 38 fields_desc = [XIntField('value', 0)] 39 40 41 class NSHTLV(Packet): 42 "NSH MD-type 2 - Variable Length Context Headers" 43 name = "NSHTLV" 44 fields_desc = [ 45 ShortField('Class', 0), 46 BitField('Critical', 0, 1), 47 BitField('Type', 0, 7), 48 BitField('Reserved', 0, 3), 49 BitField('Len', 0, 5), 50 PacketListField('Metadata', None, XIntField, count_from='Len') 51 ] 52 53 54 class NSH(Packet): 55 """Network Service Header. 56 NSH MD-type 1 if there is no ContextHeaders""" 57 name = "NSH" 58 59 fields_desc = [ 60 BitField('Ver', 0, 2), 61 BitField('OAM', 0, 1), 62 BitField('Critical', 0, 1), 63 BitField('Reserved', 0, 6), 64 BitFieldLenField('Len', None, 6, 65 count_of='ContextHeaders', 66 adjust=lambda pkt, x: 6 if pkt.MDType == 1 else x + 2), 67 ByteEnumField('MDType', 1, {1: 'Fixed Length', 68 2: 'Variable Length'}), 69 ByteEnumField('NextProto', 3, {1: 'IPv4', 70 2: 'IPv6', 71 3: 'Ethernet', 72 4: 'NSH', 73 5: 'MPLS'}), 74 X3BytesField('NSP', 0), 75 ByteField('NSI', 1), 76 ConditionalField(XIntField('NPC', 0), lambda pkt: pkt.MDType == 1), 77 ConditionalField(XIntField('NSC', 0), lambda pkt: pkt.MDType == 1), 78 ConditionalField(XIntField('SPC', 0), lambda pkt: pkt.MDType == 1), 79 ConditionalField(XIntField('SSC', 0), lambda pkt: pkt.MDType == 1), 80 ConditionalField(PacketListField("ContextHeaders", None, 81 NSHTLV, count_from="Length"), 82 lambda pkt: pkt.MDType == 2) 83 ] 84 85 def mysummary(self): 86 return self.sprintf("NSP: %NSP% - NSI: %NSI%") 87 88 89 bind_layers(Ether, NSH, {'type': 0x894F}, type=0x894F) 90 bind_layers(VXLAN, NSH, {'flags': 0xC, 'NextProtocol': 4}, NextProtocol=4) 91 bind_layers(GRE, NSH, {'proto': 0x894F}, proto=0x894F) 92 93 bind_layers(NSH, IP, {'NextProto': 1}, NextProto=1) 94 bind_layers(NSH, IPv6, {'NextProto': 2}, NextProto=2) 95 bind_layers(NSH, Ether, {'NextProto': 3}, NextProto=3) 96 bind_layers(NSH, NSH, {'NextProto': 4}, NextProto=4) 97 bind_layers(NSH, MPLS, {'NextProto': 5}, NextProto=5) 98