1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
| # 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)
|
|